
#include "stdafx.h"
#include "BlueMidnightWish.h"

namespace BMW
{
    const uint initial_state_224[16] = 
    {   
        0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 
        0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f, 
        0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f, 
        0x30313233, 0x34353637, 0x38393a3b, 0x3c3d3e3f, 
    };

    const uint initial_state_256[16] = 
    {   
        0x40414243, 0x44454647, 0x48494a4b, 0x4c4d4e4f, 
        0x50515253, 0x54555657, 0x58595a5b, 0x5c5d5e5f, 
        0x60616263, 0x64656667, 0x68696a6b, 0x6c6d6e6f, 
        0x70717273, 0x74757677, 0x78797a7b, 0x7c7d7e7f, 
    };

    const ulong initial_state_384[16] = 
    {
        0x0001020304050607, 0x08090a0b0c0d0e0f, 
        0x1011121314151617, 0x18191a1b1c1d1e1f, 
        0x2021222324252627, 0x28292a2b2c2d2e2f, 
        0x3031323334353637, 0x38393a3b3c3d3e3f, 
        0x4041424344454647, 0x48494a4b4c4d4e4f, 
        0x5051525354555657, 0x58595a5b5c5d5e5f, 
        0x6061626364656667, 0x68696a6b6c6d6e6f, 
        0x7071727374757677, 0x78797a7b7c7d7e7f
    };

    const ulong initial_state_512[16] = 
    {
        0x8081828384858687, 0x88898a8b8c8d8e8f, 
        0x9091929394959697, 0x98999a9b9c9d9e9f, 
        0xa0a1a2a3a4a5a6a7, 0xa8a9aaabacadaeaf, 
        0xb0b1b2b3b4b5b6b7, 0xb8b9babbbcbdbebf, 
        0xc0c1c2c3c4c5c6c7, 0xc8c9cacbcccdcecf, 
        0xd0d1d2d3d4d5d6d7, 0xd8d9dadbdcdddedf, 
        0xe0e1e2e3e4e5e6e7, 0xe8e9eaebecedeeef, 
        0xf0f1f2f3f4f5f6f7, 0xf8f9fafbfcfdfeff
    };
    
    void BMW256Base::TransformBlock(byte* a_data, int a_index)
    {
        uint* data32 = (uint*)(a_data + a_index);

        uint p256_00 = m_state[0] ^ data32[0];
        uint p256_01 = m_state[1] ^ data32[1];
        uint p256_02 = m_state[2] ^ data32[2];
        uint p256_03 = m_state[3] ^ data32[3];
        uint p256_04 = m_state[4] ^ data32[4];
        uint p256_05 = m_state[5] ^ data32[5];
        uint p256_06 = m_state[6] ^ data32[6];
        uint p256_07 = m_state[7] ^ data32[7];
        uint p256_08 = m_state[8] ^ data32[8];
        uint p256_09 = m_state[9] ^ data32[9];
        uint p256_10 = m_state[10] ^ data32[10];
        uint p256_11 = m_state[11] ^ data32[11];
        uint p256_12 = m_state[12] ^ data32[12];
        uint p256_13 = m_state[13] ^ data32[13];
        uint p256_14 = m_state[14] ^ data32[14];
        uint p256_15 = m_state[15] ^ data32[15];

        uint td32_00 = (data32[0] << 1) | (data32[0] >> 31);
        uint td32_01 = (data32[1] << 2) | (data32[1] >> 30);
        uint td32_02 = (data32[2] << 3) | (data32[2] >> 29);
        uint td32_03 = (data32[3] << 4) | (data32[3] >> 28);
        uint td32_04 = (data32[4] << 5) | (data32[4] >> 27);
        uint td32_05 = (data32[5] << 6) | (data32[5] >> 26);
        uint td32_06 = (data32[6] << 7) | (data32[6] >> 25);
        uint td32_07 = (data32[7] << 8) | (data32[7] >> 24);
        uint td32_08 = (data32[8] << 9) | (data32[8] >> 23);
        uint td32_09 = (data32[9] << 10) | (data32[9] >> 22);
        uint td32_10 = (data32[10] << 11) | (data32[10] >> 21);
        uint td32_11 = (data32[11] << 12) | (data32[11] >> 20);
        uint td32_12 = (data32[12] << 13) | (data32[12] >> 19);
        uint td32_13 = (data32[13] << 14) | (data32[13] >> 18);
        uint td32_14 = (data32[14] << 15) | (data32[14] >> 17);
        uint td32_15 = (data32[15] << 16) | (data32[15] >> 16);

        uint t256_16 = p256_01 - p256_14;
        uint t256_17 = p256_15 - p256_12;
        uint t256_18 = p256_14 - p256_07;
        uint t256_19 = p256_13 - p256_06;
        uint t256_20 = p256_08 - p256_05;
        uint t256_21 = p256_08 - p256_01;

        uint p256_16 = (p256_05 + t256_18 + p256_10 + p256_13);
        p256_16 = ((p256_16 >> 1) ^ (p256_16 << 3) ^ ((p256_16 << 4) | (p256_16 >> 28)) ^ ((p256_16 << 19) | (p256_16 >> 13))) + m_state[1];
        uint p256_17 = (p256_06 - p256_08 + p256_11 + p256_14 - p256_15);
        p256_17 = ((p256_17 >> 1) ^ (p256_17 << 2) ^ ((p256_17 << 8) | (p256_17 >> 24)) ^ ((p256_17 << 23) | (p256_17 >> 9))) + m_state[2];
        uint p256_18 = (p256_00 + p256_07 + p256_09 + t256_17);
        p256_18 = ((p256_18 >> 2) ^ (p256_18 << 1) ^ ((p256_18 << 12) | (p256_18 >> 20)) ^ ((p256_18 << 25) | (p256_18 >> 7))) + m_state[3];
        uint p256_19 = (p256_00 + t256_21 - p256_10 + p256_13);
        p256_19 = ((p256_19 >> 2) ^ (p256_19 << 2) ^ ((p256_19 << 15) | (p256_19 >> 17)) ^ ((p256_19 << 29) | (p256_19 >> 3))) + m_state[4];
        uint p256_20 = (t256_16 + p256_02 + p256_09 - p256_11);
        p256_20 = ((p256_20 >> 1) ^ p256_20) + m_state[5];
        uint p256_21 = (p256_03 - p256_02 + p256_10 + t256_17);
        p256_21 = ((p256_21 >> 1) ^ (p256_21 << 3) ^ ((p256_21 << 4) | (p256_21 >> 28)) ^ ((p256_21 << 19) | (p256_21 >> 13))) + m_state[6];
        uint p256_22 = (p256_04 - p256_00 - p256_03 - p256_11 + p256_13);
        p256_22 = ((p256_22 >> 1) ^ (p256_22 << 2) ^ ((p256_22 << 8) | (p256_22 >> 24)) ^ ((p256_22 << 23) | (p256_22 >> 9))) + m_state[7];
        uint p256_23 = (t256_16 - p256_04 - p256_05 - p256_12);
        p256_23 = ((p256_23 >> 2) ^ (p256_23 << 1) ^ ((p256_23 << 12) | (p256_23 >> 20)) ^ ((p256_23 << 25) | (p256_23 >> 7))) + m_state[8];
        uint p256_24 = (p256_02 - p256_05 + t256_19 - p256_15);
        p256_24 = ((p256_24 >> 2) ^ (p256_24 << 2) ^ ((p256_24 << 15) | (p256_24 >> 17)) ^ ((p256_24 << 29) | (p256_24 >> 3))) + m_state[9];
        uint p256_25 = (p256_00 - p256_03 + p256_06 + t256_18);
        p256_25 = ((p256_25 >> 1) ^ p256_25) + m_state[10];
        uint p256_26 = (t256_21 - p256_04 - p256_07 + p256_15);
        p256_26 = ((p256_26 >> 1) ^ (p256_26 << 3) ^ ((p256_26 << 4) | (p256_26 >> 28)) ^ ((p256_26 << 19) | (p256_26 >> 13))) + m_state[11];
        uint p256_27 = (t256_20 - p256_00 - p256_02 + p256_09);
        p256_27 = ((p256_27 >> 1) ^ (p256_27 << 2) ^ ((p256_27 << 8) | (p256_27 >> 24)) ^ ((p256_27 << 23) | (p256_27 >> 9))) + m_state[12];
        uint p256_28 = (p256_01 + p256_03 - p256_06 - p256_09 + p256_10);
        p256_28 = ((p256_28 >> 2) ^ (p256_28 << 1) ^ ((p256_28 << 12) | (p256_28 >> 20)) ^ ((p256_28 << 25) | (p256_28 >> 7))) + m_state[13];
        uint p256_29 = (p256_02 + p256_04 + p256_07 + p256_10 + p256_11);
        p256_29 = ((p256_29 >> 2) ^ (p256_29 << 2) ^ ((p256_29 << 15) | (p256_29 >> 17)) ^ ((p256_29 << 29) | (p256_29 >> 3))) + m_state[14];
        uint p256_30 = (p256_03 + t256_20 - p256_11 - p256_12);
        p256_14 = ((p256_30 >> 1) ^ p256_30) + m_state[15];
        uint p256_31 = (p256_12 - p256_04 + t256_19 - p256_09);
        p256_15 = ((p256_31 >> 1) ^ (p256_31 << 3) ^ ((p256_31 << 4) | (p256_31 >> 28)) ^ ((p256_31 << 19) | (p256_31 >> 13))) + m_state[0];

        p256_00 = p256_16;
        p256_01 = p256_17;
        p256_02 = p256_18;
        p256_03 = p256_19;
        p256_04 = p256_20;
        p256_05 = p256_21;
        p256_06 = p256_22;
        p256_07 = p256_23;
        p256_08 = p256_24;
        p256_09 = p256_25;
        p256_10 = p256_26;
        p256_11 = p256_27;
        p256_12 = p256_28;
        p256_13 = p256_29;

        p256_16 = ((p256_00 >> 1) ^ (p256_00 << 2) ^ ((p256_00 << 8) | (p256_00 >> 24)) ^ ((p256_00 << 23) | (p256_00 >> 9))) + 
                  ((p256_01 >> 2) ^ (p256_01 << 1) ^ ((p256_01 << 12) | (p256_01 >> 20)) ^ ((p256_01 << 25) | (p256_01 >> 7))) + 
                  ((p256_02 >> 2) ^ (p256_02 << 2) ^ ((p256_02 << 15) | (p256_02 >> 17)) ^ ((p256_02 << 29) | (p256_02 >> 3))) + 
                  ((p256_03 >> 1) ^ (p256_03 << 3) ^ ((p256_03 << 4) | (p256_03 >> 28)) ^ ((p256_03 << 19) | (p256_03 >> 13))) + 
                  ((p256_04 >> 1) ^ (p256_04 << 2) ^ ((p256_04 << 8) | (p256_04 >> 24)) ^ ((p256_04 << 23) | (p256_04 >> 9))) + 
                  ((p256_05 >> 2) ^ (p256_05 << 1) ^ ((p256_05 << 12) | (p256_05 >> 20)) ^ ((p256_05 << 25) | (p256_05 >> 7))) + 
                  ((p256_06 >> 2) ^ (p256_06 << 2) ^ ((p256_06 << 15) | (p256_06 >> 17)) ^ ((p256_06 << 29) | (p256_06 >> 3))) + 
                  ((p256_07 >> 1) ^ (p256_07 << 3) ^ ((p256_07 << 4) | (p256_07 >> 28)) ^ ((p256_07 << 19) | (p256_07 >> 13))) + 
                  ((p256_08 >> 1) ^ (p256_08 << 2) ^ ((p256_08 << 8) | (p256_08 >> 24)) ^ ((p256_08 << 23) | (p256_08 >> 9))) + 
                  ((p256_09 >> 2) ^ (p256_09 << 1) ^ ((p256_09 << 12) | (p256_09 >> 20)) ^ ((p256_09 << 25) | (p256_09 >> 7))) + 
                  ((p256_10 >> 2) ^ (p256_10 << 2) ^ ((p256_10 << 15) | (p256_10 >> 17)) ^ ((p256_10 << 29) | (p256_10 >> 3))) + 
                  ((p256_11 >> 1) ^ (p256_11 << 3) ^ ((p256_11 << 4) | (p256_11 >> 28)) ^ ((p256_11 << 19) | (p256_11 >> 13))) + 
                  ((p256_12 >> 1) ^ (p256_12 << 2) ^ ((p256_12 << 8) | (p256_12 >> 24)) ^ ((p256_12 << 23) | (p256_12 >> 9))) + 
                  ((p256_13 >> 2) ^ (p256_13 << 1) ^ ((p256_13 << 12) | (p256_13 >> 20)) ^ ((p256_13 << 25) | (p256_13 >> 7))) + 
                  ((p256_14 >> 2) ^ (p256_14 << 2) ^ ((p256_14 << 15) | (p256_14 >> 17)) ^ ((p256_14 << 29) | (p256_14 >> 3))) + 
                  ((p256_15 >> 1) ^ (p256_15 << 3) ^ ((p256_15 << 4) | (p256_15 >> 28)) ^ ((p256_15 << 19) | (p256_15 >> 13))) + 
                  ((td32_00 + td32_03 - td32_10 + 0x55555550) ^ m_state[7]);

        uint XL32 = p256_16;

        p256_17 = ((p256_01 >> 1) ^ (p256_01 << 2) ^ ((p256_01 << 8) | (p256_01 >> 24)) ^ ((p256_01 << 23) | (p256_01 >> 9))) + 
                  ((p256_02 >> 2) ^ (p256_02 << 1) ^ ((p256_02 << 12) | (p256_02 >> 20)) ^ ((p256_02 << 25) | (p256_02 >> 7))) + 
                  ((p256_03 >> 2) ^ (p256_03 << 2) ^ ((p256_03 << 15) | (p256_03 >> 17)) ^ ((p256_03 << 29) | (p256_03 >> 3))) + 
                  ((p256_04 >> 1) ^ (p256_04 << 3) ^ ((p256_04 << 4) | (p256_04 >> 28)) ^ ((p256_04 << 19) | (p256_04 >> 13))) + 
                  ((p256_05 >> 1) ^ (p256_05 << 2) ^ ((p256_05 << 8) | (p256_05 >> 24)) ^ ((p256_05 << 23) | (p256_05 >> 9))) + 
                  ((p256_06 >> 2) ^ (p256_06 << 1) ^ ((p256_06 << 12) | (p256_06 >> 20)) ^ ((p256_06 << 25) | (p256_06 >> 7))) + 
                  ((p256_07 >> 2) ^ (p256_07 << 2) ^ ((p256_07 << 15) | (p256_07 >> 17)) ^ ((p256_07 << 29) | (p256_07 >> 3))) + 
                  ((p256_08 >> 1) ^ (p256_08 << 3) ^ ((p256_08 << 4) | (p256_08 >> 28)) ^ ((p256_08 << 19) | (p256_08 >> 13))) + 
                  ((p256_09 >> 1) ^ (p256_09 << 2) ^ ((p256_09 << 8) | (p256_09 >> 24)) ^ ((p256_09 << 23) | (p256_09 >> 9))) + 
                  ((p256_10 >> 2) ^ (p256_10 << 1) ^ ((p256_10 << 12) | (p256_10 >> 20)) ^ ((p256_10 << 25) | (p256_10 >> 7))) + 
                  ((p256_11 >> 2) ^ (p256_11 << 2) ^ ((p256_11 << 15) | (p256_11 >> 17)) ^ ((p256_11 << 29) | (p256_11 >> 3))) + 
                  ((p256_12 >> 1) ^ (p256_12 << 3) ^ ((p256_12 << 4) | (p256_12 >> 28)) ^ ((p256_12 << 19) | (p256_12 >> 13))) + 
                  ((p256_13 >> 1) ^ (p256_13 << 2) ^ ((p256_13 << 8) | (p256_13 >> 24)) ^ ((p256_13 << 23) | (p256_13 >> 9))) + 
                  ((p256_14 >> 2) ^ (p256_14 << 1) ^ ((p256_14 << 12) | (p256_14 >> 20)) ^ ((p256_14 << 25) | (p256_14 >> 7))) + 
                  ((p256_15 >> 2) ^ (p256_15 << 2) ^ ((p256_15 << 15) | (p256_15 >> 17)) ^ ((p256_15 << 29) | (p256_15 >> 3))) + 
                  ((p256_16 >> 1) ^ (p256_16 << 3) ^ ((p256_16 << 4) | (p256_16 >> 28)) ^ ((p256_16 << 19) | (p256_16 >> 13))) + 
                  ((td32_01 + td32_04 - td32_11 + 0x5aaaaaa5) ^ m_state[8]);

        XL32 ^= p256_17;
        uint TempEven32 = p256_14 + p256_12 + p256_10 + p256_08 + p256_06 + p256_04 + p256_02;
        uint TempOdd32 = p256_15 + p256_13 + p256_11 + p256_09 + p256_07 + p256_05 + p256_03;

        p256_18 = TempEven32 + 
                  ((p256_03 << 3) | (p256_03 >> 29)) + 
                  ((p256_05 << 7) | (p256_05 >> 25)) + 
                  ((p256_07 << 13) | (p256_07 >> 19)) + 
                  ((p256_09 << 16) | (p256_09 >> 16)) + 
                  ((p256_11 << 19) | (p256_11 >> 13)) + 
                  ((p256_13 << 23) | (p256_13 >> 9)) + 
                  ((p256_15 << 27) | (p256_15 >> 5)) + 
                  ((p256_16 >> 1) ^ p256_16) + 
                  ((p256_17 >> 2) ^ p256_17) + 
                  ((td32_02 + td32_05 - td32_12 + 0x5ffffffa) ^ m_state[9]);

        XL32 ^= p256_18;

        p256_19 = TempOdd32 + 
                  ((p256_04 << 3) | (p256_04 >> 29)) + 
                  ((p256_06 << 7) | (p256_06 >> 25)) + 
                  ((p256_08 << 13) | (p256_08 >> 19)) + 
                  ((p256_10 << 16) | (p256_10 >> 16)) + 
                  ((p256_12 << 19) | (p256_12 >> 13)) + 
                  ((p256_14 << 23) | (p256_14 >> 9)) + 
                  ((p256_16 << 27) | (p256_16 >> 5)) + 
                  ((p256_17 >> 1) ^ p256_17) + 
                  ((p256_18 >> 2) ^ p256_18) + 
                  ((td32_03 + td32_06 - td32_13 + 0x6555554f) ^ m_state[10]);

        XL32 ^= p256_19;
        TempEven32 = TempEven32 + p256_16 - p256_02;

        p256_20 = TempEven32 + 
                  ((p256_05 << 3) | (p256_05 >> 29)) + 
                  ((p256_07 << 7) | (p256_07 >> 25)) + 
                  ((p256_09 << 13) | (p256_09 >> 19)) + 
                  ((p256_11 << 16) | (p256_11 >> 16)) + 
                  ((p256_13 << 19) | (p256_13 >> 13)) + 
                  ((p256_15 << 23) | (p256_15 >> 9)) + 
                  ((p256_17 << 27) | (p256_17 >> 5)) + 
                  ((p256_18 >> 1) ^ p256_18) + 
                  ((p256_19 >> 2) ^ p256_19) + 
                  ((td32_04 + td32_07 - td32_14 + 0x6aaaaaa4) ^ m_state[11]);

        XL32 ^= p256_20;
        TempOdd32 = TempOdd32 + p256_17 - p256_03;

        p256_21 = TempOdd32 + 
                  ((p256_06 << 3) | (p256_06 >> 29)) + 
                  ((p256_08 << 7) | (p256_08 >> 25)) + 
                  ((p256_10 << 13) | (p256_10 >> 19)) + 
                  ((p256_12 << 16) | (p256_12 >> 16)) + 
                  ((p256_14 << 19) | (p256_14 >> 13)) + 
                  ((p256_16 << 23) | (p256_16 >> 9)) + 
                  ((p256_18 << 27) | (p256_18 >> 5)) + 
                  ((p256_19 >> 1) ^ p256_19) + 
                  ((p256_20 >> 2) ^ p256_20) + 
                  ((td32_05 + td32_08 - td32_15 + 0x6ffffff9) ^ m_state[12]);

        XL32 ^= p256_21;
        TempEven32 = TempEven32 + p256_18 - p256_04;

        p256_22 = TempEven32 + 
                  ((p256_07 << 3) | (p256_07 >> 29)) + 
                  ((p256_09 << 7) | (p256_09 >> 25)) + 
                  ((p256_11 << 13) | (p256_11 >> 19)) + 
                  ((p256_13 << 16) | (p256_13 >> 16)) + 
                  ((p256_15 << 19) | (p256_15 >> 13)) + 
                  ((p256_17 << 23) | (p256_17 >> 9)) + 
                  ((p256_19 << 27) | (p256_19 >> 5)) + 
                  ((p256_20 >> 1) ^ p256_20) + 
                  ((p256_21 >> 2) ^ p256_21) + 
                  ((td32_06 + td32_09 - td32_00 + 0x7555554e) ^ m_state[13]);

        XL32 ^= p256_22;
        TempOdd32 = TempOdd32 + p256_19 - p256_05;

        p256_23 = TempOdd32 + 
                  ((p256_08 << 3) | (p256_08 >> 29)) + 
                  ((p256_10 << 7) | (p256_10 >> 25)) + 
                  ((p256_12 << 13) | (p256_12 >> 19)) + 
                  ((p256_14 << 16) | (p256_14 >> 16)) + 
                  ((p256_16 << 19) | (p256_16 >> 13)) + 
                  ((p256_18 << 23) | (p256_18 >> 9)) + 
                  ((p256_20 << 27) | (p256_20 >> 5)) + 
                  ((p256_21 >> 1) ^ p256_21) + 
                  ((p256_22 >> 2) ^ p256_22) + 
                  ((td32_07 + td32_10 - td32_01 + 0x7aaaaaa3) ^ m_state[14]);

        XL32 ^= p256_23;
        TempEven32 = TempEven32 + p256_20 - p256_06;

        p256_24 = TempEven32 + 
                  ((p256_09 << 3) | (p256_09 >> 29)) + 
                  ((p256_11 << 7) | (p256_11 >> 25)) + 
                  ((p256_13 << 13) | (p256_13 >> 19)) + 
                  ((p256_15 << 16) | (p256_15 >> 16)) + 
                  ((p256_17 << 19) | (p256_17 >> 13)) + 
                  ((p256_19 << 23) | (p256_19 >> 9)) + 
                  ((p256_21 << 27) | (p256_21 >> 5)) + 
                  ((p256_22 >> 1) ^ p256_22) + 
                  ((p256_23 >> 2) ^ p256_23) + 
                  ((td32_08 + td32_11 - td32_02 + 0x7ffffff8) ^ m_state[15]);

        uint XH32 = XL32 ^ p256_24;
        TempOdd32 = TempOdd32 + p256_21 - p256_07;

        p256_25 = TempOdd32 + 
                  ((p256_10 << 3) | (p256_10 >> 29)) + 
                  ((p256_12 << 7) | (p256_12 >> 25)) + 
                  ((p256_14 << 13) | (p256_14 >> 19)) + 
                  ((p256_16 << 16) | (p256_16 >> 16)) + 
                  ((p256_18 << 19) | (p256_18 >> 13)) + 
                  ((p256_20 << 23) | (p256_20 >> 9)) + 
                  ((p256_22 << 27) | (p256_22 >> 5)) + 
                  ((p256_23 >> 1) ^ p256_23) + 
                  ((p256_24 >> 2) ^ p256_24) + 
                  ((td32_09 + td32_12 - td32_03 + 0x8555554d) ^ m_state[0]);

        XH32 ^= p256_25;
        TempEven32 = TempEven32 + p256_22 - p256_08;

        p256_26 = TempEven32 + 
                  ((p256_11 << 3) | (p256_11 >> 29)) + 
                  ((p256_13 << 7) | (p256_13 >> 25)) + 
                  ((p256_15 << 13) | (p256_15 >> 19)) + 
                  ((p256_17 << 16) | (p256_17 >> 16)) + 
                  ((p256_19 << 19) | (p256_19 >> 13)) + 
                  ((p256_21 << 23) | (p256_21 >> 9)) + 
                  ((p256_23 << 27) | (p256_23 >> 5)) + 
                  ((p256_24 >> 1) ^ p256_24) + 
                  ((p256_25 >> 2) ^ p256_25) + 
                  ((td32_10 + td32_13 - td32_04 + 0x8aaaaaa2) ^ m_state[1]);

        XH32 ^= p256_26;
        TempOdd32 = TempOdd32 + p256_23 - p256_09;

        p256_27 = TempOdd32 + 
                  ((p256_12 << 3) | (p256_12 >> 29)) + 
                  ((p256_14 << 7) | (p256_14 >> 25)) + 
                  ((p256_16 << 13) | (p256_16 >> 19)) + 
                  ((p256_18 << 16) | (p256_18 >> 16)) + 
                  ((p256_20 << 19) | (p256_20 >> 13)) + 
                  ((p256_22 << 23) | (p256_22 >> 9)) + 
                  ((p256_24 << 27) | (p256_24 >> 5)) + 
                  ((p256_25 >> 1) ^ p256_25) + 
                  ((p256_26 >> 2) ^ p256_26) + 
                  ((td32_11 + td32_14 - td32_05 + 0x8ffffff7) ^ m_state[2]);

        XH32 ^= p256_27;
        TempEven32 = TempEven32 + p256_24 - p256_10;

        p256_28 = TempEven32 + 
                  ((p256_13 << 3) | (p256_13 >> 29)) + 
                  ((p256_15 << 7) | (p256_15 >> 25)) + 
                  ((p256_17 << 13) | (p256_17 >> 19)) + 
                  ((p256_19 << 16) | (p256_19 >> 16)) + 
                  ((p256_21 << 19) | (p256_21 >> 13)) + 
                  ((p256_23 << 23) | (p256_23 >> 9)) + 
                  ((p256_25 << 27) | (p256_25 >> 5)) + 
                  ((p256_26 >> 1) ^ p256_26) + ((p256_27 >> 2) ^ p256_27) + 
                  ((td32_12 + td32_15 - td32_06 + 0x9555554c) ^ m_state[3]);

        XH32 ^= p256_28;
        TempOdd32 = TempOdd32 + p256_25 - p256_11;

        p256_29 = TempOdd32 + 
                  ((p256_14 << 3) | (p256_14 >> 29)) + 
                  ((p256_16 << 7) | (p256_16 >> 25)) + 
                  ((p256_18 << 13) | (p256_18 >> 19)) + 
                  ((p256_20 << 16) | (p256_20 >> 16)) + 
                  ((p256_22 << 19) | (p256_22 >> 13)) + 
                  ((p256_24 << 23) | (p256_24 >> 9)) + 
                  ((p256_26 << 27) | (p256_26 >> 5)) + 
                  ((p256_27 >> 1) ^ p256_27) + 
                  ((p256_28 >> 2) ^ p256_28) + 
                  ((td32_13 + td32_00 - td32_07 + 0x9aaaaaa1) ^ m_state[4]);

        XH32 ^= p256_29;
        TempEven32 = TempEven32 + p256_26 - p256_12;

        p256_30 = TempEven32 + 
                  ((p256_15 << 3) | (p256_15 >> 29)) + 
                  ((p256_17 << 7) | (p256_17 >> 25)) + 
                  ((p256_19 << 13) | (p256_19 >> 19)) + 
                  ((p256_21 << 16) | (p256_21 >> 16)) + 
                  ((p256_23 << 19) | (p256_23 >> 13)) + 
                  ((p256_25 << 23) | (p256_25 >> 9)) + 
                  ((p256_27 << 27) | (p256_27 >> 5)) + 
                  ((p256_28 >> 1) ^ p256_28) + 
                  ((p256_29 >> 2) ^ p256_29) + 
                  ((td32_14 + td32_01 - td32_08 + 0x9ffffff6) ^ m_state[5]);

        XH32 ^= p256_30;
        TempOdd32 = TempOdd32 + p256_27 - p256_13;

        p256_31 = TempOdd32 + 
                  ((p256_16 << 3) | (p256_16 >> 29)) + 
                  ((p256_18 << 7) | (p256_18 >> 25)) + 
                  ((p256_20 << 13) | (p256_20 >> 19)) + 
                  ((p256_22 << 16) | (p256_22 >> 16)) + 
                  ((p256_24 << 19) | (p256_24 >> 13)) + 
                  ((p256_26 << 23) | (p256_26 >> 9)) + 
                  ((p256_28 << 27) | (p256_28 >> 5)) + 
                  ((p256_29 >> 1) ^ p256_29) + 
                  ((p256_30 >> 2) ^ p256_30) + 
                  ((td32_15 + td32_02 - td32_09 + 0xa555554b) ^ m_state[6]);

        XH32 ^= p256_31;

        m_state[0] = ((XH32 << 5) ^ (p256_16 >> 5) ^ data32[0]) + ( XL32 ^ p256_24 ^ p256_00);
        m_state[1] = ((XH32 >> 7) ^ (p256_17 << 8) ^ data32[1]) + ( XL32 ^ p256_25 ^ p256_01);
        m_state[2] = ((XH32 >> 5) ^ (p256_18 << 5) ^ data32[2]) + ( XL32 ^ p256_26 ^ p256_02);
        m_state[3] = ((XH32 >> 1) ^ (p256_19 << 5) ^ data32[3]) + ( XL32 ^ p256_27 ^ p256_03);
        m_state[4] = ((XH32 >> 3) ^ p256_20 ^ data32[4]) + ( XL32 ^ p256_28 ^ p256_04);
        m_state[5] = ((XH32 << 6) ^ (p256_21 >> 6) ^ data32[5]) + ( XL32 ^ p256_29 ^ p256_05);
        m_state[6] = ((XH32 >> 4) ^ (p256_22 << 6) ^ data32[6]) + ( XL32 ^ p256_30 ^ p256_06);
        m_state[7] = ((XH32 >> 11) ^ (p256_23 << 2) ^ data32[7]) + ( XL32 ^ p256_31 ^ p256_07);

        m_state[8] = ((m_state[4] << 9) | (m_state[4] >> 23)) + ( XH32 ^ p256_24 ^ data32[8]) + ((XL32 << 8) ^ p256_23 ^ p256_08);
        m_state[9] = ((m_state[5] << 10) | (m_state[5] >> 22)) + ( XH32 ^ p256_25 ^ data32[9]) + ((XL32 >> 6) ^ p256_16 ^ p256_09);
        m_state[10] = ((m_state[6] << 11) | (m_state[6] >> 21)) + ( XH32 ^ p256_26 ^ data32[10]) + ((XL32 << 6) ^ p256_17 ^ p256_10);
        m_state[11] = ((m_state[7] << 12) | (m_state[7] >> 20)) + ( XH32 ^ p256_27 ^ data32[11]) + ((XL32 << 4) ^ p256_18 ^ p256_11);
        m_state[12] = ((m_state[0] << 13) | (m_state[0] >> 19)) + ( XH32 ^ p256_28 ^ data32[12]) + ((XL32 >> 3) ^ p256_19 ^ p256_12);
        m_state[13] = ((m_state[1] << 14) | (m_state[1] >> 18)) + ( XH32 ^ p256_29 ^ data32[13]) + ((XL32 >> 4) ^ p256_20 ^ p256_13);
        m_state[14] = ((m_state[2] << 15) | (m_state[2] >> 17)) + ( XH32 ^ p256_30 ^ data32[14]) + ((XL32 >> 7) ^ p256_21 ^ p256_14);
        m_state[15] = ((m_state[3] << 16) | (m_state[3] >> 16)) + ( XH32 ^ p256_31 ^ data32[15]) + ((XL32 >> 2) ^ p256_22 ^ p256_15);
    }

    void BMW256Base::FinalCompression() 
    {
        uint p256_00 = m_state[0] ^ 0xaaaaaaa0;
        uint p256_01 = m_state[1] ^ 0xaaaaaaa1;
        uint p256_02 = m_state[2] ^ 0xaaaaaaa2;
        uint p256_03 = m_state[3] ^ 0xaaaaaaa3;
        uint p256_04 = m_state[4] ^ 0xaaaaaaa4;
        uint p256_05 = m_state[5] ^ 0xaaaaaaa5;
        uint p256_06 = m_state[6] ^ 0xaaaaaaa6;
        uint p256_07 = m_state[7] ^ 0xaaaaaaa7;
        uint p256_08 = m_state[8] ^ 0xaaaaaaa8;
        uint p256_09 = m_state[9] ^ 0xaaaaaaa9;
        uint p256_10 = m_state[10] ^ 0xaaaaaaaa;
        uint p256_11 = m_state[11] ^ 0xaaaaaaab;
        uint p256_12 = m_state[12] ^ 0xaaaaaaac;
        uint p256_13 = m_state[13] ^ 0xaaaaaaad;
        uint p256_14 = m_state[14] ^ 0xaaaaaaae;
        uint p256_15 = m_state[15] ^ 0xaaaaaaaf;

        uint td32_00 = (m_state[0] << 1) | (m_state[0] >> 31);
        uint td32_01 = (m_state[1] << 2) | (m_state[1] >> 30);
        uint td32_02 = (m_state[2] << 3) | (m_state[2] >> 29);
        uint td32_03 = (m_state[3] << 4) | (m_state[3] >> 28);
        uint td32_04 = (m_state[4] << 5) | (m_state[4] >> 27);
        uint td32_05 = (m_state[5] << 6) | (m_state[5] >> 26);
        uint td32_06 = (m_state[6] << 7) | (m_state[6] >> 25);
        uint td32_07 = (m_state[7] << 8) | (m_state[7] >> 24);
        uint td32_08 = (m_state[8] << 9) | (m_state[8] >> 23);
        uint td32_09 = (m_state[9] << 10) | (m_state[9] >> 22);
        uint td32_10 = (m_state[10] << 11) | (m_state[10] >> 21);
        uint td32_11 = (m_state[11] << 12) | (m_state[11] >> 20);
        uint td32_12 = (m_state[12] << 13) | (m_state[12] >> 19);
        uint td32_13 = (m_state[13] << 14) | (m_state[13] >> 18);
        uint td32_14 = (m_state[14] << 15) | (m_state[14] >> 17);
        uint td32_15 = (m_state[15] << 16) | (m_state[15] >> 16);

        uint t256_16 = p256_01 - p256_14;
        uint t256_17 = p256_15 - p256_12;
        uint t256_18 = p256_14 - p256_07;
        uint t256_19 = p256_13 - p256_06;
        uint t256_20 = p256_08 - p256_05;
        uint t256_21 = p256_08 - p256_01;

        uint p256_16 = (p256_05 + t256_18 + p256_10 + p256_13);
        p256_16 = ((p256_16 >> 1) ^ (p256_16 << 3) ^ ((p256_16 << 4) | (p256_16 >> 28)) ^ ((p256_16 << 19) | (p256_16 >> 13))) + 0xaaaaaaa1;
        uint p256_17 = (p256_06 - p256_08 + p256_11 + p256_14 - p256_15);
        p256_17 = ((p256_17 >> 1) ^ (p256_17 << 2) ^ ((p256_17 << 8) | (p256_17 >> 24)) ^ ((p256_17 << 23) | (p256_17 >> 9))) + 0xaaaaaaa2;
        uint p256_18 = (p256_00 + p256_07 + p256_09 + t256_17);
        p256_18 = ((p256_18 >> 2) ^ (p256_18 << 1) ^ ((p256_18 << 12) | (p256_18 >> 20)) ^ ((p256_18 << 25) | (p256_18 >> 7))) + 0xaaaaaaa3;
        uint p256_19 = (p256_00 + t256_21 - p256_10 + p256_13);
        p256_19 = ((p256_19 >> 2) ^ (p256_19 << 2) ^ ((p256_19 << 15) | (p256_19 >> 17)) ^ ((p256_19 << 29) | (p256_19 >> 3))) + 0xaaaaaaa4;
        uint p256_20 = (t256_16 + p256_02 + p256_09 - p256_11);
        p256_20 = ((p256_20 >> 1) ^ p256_20) + 0xaaaaaaa5;
        uint p256_21 = (p256_03 - p256_02 + p256_10 + t256_17);
        p256_21 = ((p256_21 >> 1) ^ (p256_21 << 3) ^ ((p256_21 << 4) | (p256_21 >> 28)) ^ ((p256_21 << 19) | (p256_21 >> 13))) + 0xaaaaaaa6;
        uint p256_22 = (p256_04 - p256_00 - p256_03 - p256_11 + p256_13);
        p256_22 = ((p256_22 >> 1) ^ (p256_22 << 2) ^ ((p256_22 << 8) | (p256_22 >> 24)) ^ ((p256_22 << 23) | (p256_22 >> 9))) + 0xaaaaaaa7;
        uint p256_23 = (t256_16 - p256_04 - p256_05 - p256_12);
        p256_23 = ((p256_23 >> 2) ^ (p256_23 << 1) ^ ((p256_23 << 12) | (p256_23 >> 20)) ^ ((p256_23 << 25) | (p256_23 >> 7))) + 0xaaaaaaa8;
        uint p256_24 = (p256_02 - p256_05 + t256_19 - p256_15);
        p256_24 = ((p256_24 >> 2) ^ (p256_24 << 2) ^ ((p256_24 << 15) | (p256_24 >> 17)) ^ ((p256_24 << 29) | (p256_24 >> 3))) + 0xaaaaaaa9;
        uint p256_25 = (p256_00 - p256_03 + p256_06 + t256_18);
        p256_25 = ((p256_25 >> 1) ^ p256_25) + 0xaaaaaaaa;
        uint p256_26 = (t256_21 - p256_04 - p256_07 + p256_15);
        p256_26 = ((p256_26 >> 1) ^ (p256_26 << 3) ^ ((p256_26 << 4) | (p256_26 >> 28)) ^ ((p256_26 << 19) | (p256_26 >> 13))) + 0xaaaaaaab;
        uint p256_27 = (t256_20 - p256_00 - p256_02 + p256_09);
        p256_27 = ((p256_27 >> 1) ^ (p256_27 << 2) ^ ((p256_27 << 8) | (p256_27 >> 24)) ^ ((p256_27 << 23) | (p256_27 >> 9))) + 0xaaaaaaac;
        uint p256_28 = (p256_01 + p256_03 - p256_06 - p256_09 + p256_10);
        p256_28 = ((p256_28 >> 2) ^ (p256_28 << 1) ^ ((p256_28 << 12) | (p256_28 >> 20)) ^ ((p256_28 << 25) | (p256_28 >> 7))) + 0xaaaaaaad;
        uint p256_29 = (p256_02 + p256_04 + p256_07 + p256_10 + p256_11);
        p256_29 = ((p256_29 >> 2) ^ (p256_29 << 2) ^ ((p256_29 << 15) | (p256_29 >> 17)) ^ ((p256_29 << 29) | (p256_29 >> 3))) + 0xaaaaaaae;
        uint p256_30 = (p256_03 + t256_20 - p256_11 - p256_12);
        p256_14 = ((p256_30 >> 1) ^ p256_30) + 0xaaaaaaaf;
        uint p256_31 = (p256_12 - p256_04 + t256_19 - p256_09);
        p256_15 = ((p256_31 >> 1) ^ (p256_31 << 3) ^ ((p256_31 << 4) | (p256_31 >> 28)) ^ ((p256_31 << 19) | (p256_31 >> 13))) + 0xaaaaaaa0;

        p256_00 = p256_16;
        p256_01 = p256_17;
        p256_02 = p256_18;
        p256_03 = p256_19;
        p256_04 = p256_20;
        p256_05 = p256_21;
        p256_06 = p256_22;
        p256_07 = p256_23;
        p256_08 = p256_24;
        p256_09 = p256_25;
        p256_10 = p256_26;
        p256_11 = p256_27;
        p256_12 = p256_28;
        p256_13 = p256_29;

        p256_16 = ((p256_00 >> 1) ^ (p256_00 << 2) ^ ((p256_00 << 8) | (p256_00 >> 24)) ^ ((p256_00 << 23) | (p256_00 >> 9))) + 
                  ((p256_01 >> 2) ^ (p256_01 << 1) ^ ((p256_01 << 12) | (p256_01 >> 20)) ^ ((p256_01 << 25) | (p256_01 >> 7))) + 
                  ((p256_02 >> 2) ^ (p256_02 << 2) ^ ((p256_02 << 15) | (p256_02 >> 17)) ^ ((p256_02 << 29) | (p256_02 >> 3))) + 
                  ((p256_03 >> 1) ^ (p256_03 << 3) ^ ((p256_03 << 4) | (p256_03 >> 28)) ^ ((p256_03 << 19) | (p256_03 >> 13))) + 
                  ((p256_04 >> 1) ^ (p256_04 << 2) ^ ((p256_04 << 8) | (p256_04 >> 24)) ^ ((p256_04 << 23) | (p256_04 >> 9))) + 
                  ((p256_05 >> 2) ^ (p256_05 << 1) ^ ((p256_05 << 12) | (p256_05 >> 20)) ^ ((p256_05 << 25) | (p256_05 >> 7))) + 
                  ((p256_06 >> 2) ^ (p256_06 << 2) ^ ((p256_06 << 15) | (p256_06 >> 17)) ^ ((p256_06 << 29) | (p256_06 >> 3))) + 
                  ((p256_07 >> 1) ^ (p256_07 << 3) ^ ((p256_07 << 4) | (p256_07 >> 28)) ^ ((p256_07 << 19) | (p256_07 >> 13))) + 
                  ((p256_08 >> 1) ^ (p256_08 << 2) ^ ((p256_08 << 8) | (p256_08 >> 24)) ^ ((p256_08 << 23) | (p256_08 >> 9))) + 
                  ((p256_09 >> 2) ^ (p256_09 << 1) ^ ((p256_09 << 12) | (p256_09 >> 20)) ^ ((p256_09 << 25) | (p256_09 >> 7))) + 
                  ((p256_10 >> 2) ^ (p256_10 << 2) ^ ((p256_10 << 15) | (p256_10 >> 17)) ^ ((p256_10 << 29) | (p256_10 >> 3))) + 
                  ((p256_11 >> 1) ^ (p256_11 << 3) ^ ((p256_11 << 4) | (p256_11 >> 28)) ^ ((p256_11 << 19) | (p256_11 >> 13))) + 
                  ((p256_12 >> 1) ^ (p256_12 << 2) ^ ((p256_12 << 8) | (p256_12 >> 24)) ^ ((p256_12 << 23) | (p256_12 >> 9))) + 
                  ((p256_13 >> 2) ^ (p256_13 << 1) ^ ((p256_13 << 12) | (p256_13 >> 20)) ^ ((p256_13 << 25) | (p256_13 >> 7))) + 
                  ((p256_14 >> 2) ^ (p256_14 << 2) ^ ((p256_14 << 15) | (p256_14 >> 17)) ^ ((p256_14 << 29) | (p256_14 >> 3))) + 
                  ((p256_15 >> 1) ^ (p256_15 << 3) ^ ((p256_15 << 4) | (p256_15 >> 28)) ^ ((p256_15 << 19) | (p256_15 >> 13))) + 
                  ((td32_00 + td32_03 - td32_10 + 0x55555550) ^ 0xaaaaaaa7);

        uint XL32 = p256_16;

        p256_17 = ((p256_01 >> 1) ^ (p256_01 << 2) ^ ((p256_01 << 8) | (p256_01 >> 24)) ^ ((p256_01 << 23) | (p256_01 >> 9))) + 
                  ((p256_02 >> 2) ^ (p256_02 << 1) ^ ((p256_02 << 12) | (p256_02 >> 20)) ^ ((p256_02 << 25) | (p256_02 >> 7))) + 
                  ((p256_03 >> 2) ^ (p256_03 << 2) ^ ((p256_03 << 15) | (p256_03 >> 17)) ^ ((p256_03 << 29) | (p256_03 >> 3))) + 
                  ((p256_04 >> 1) ^ (p256_04 << 3) ^ ((p256_04 << 4) | (p256_04 >> 28)) ^ ((p256_04 << 19) | (p256_04 >> 13))) + 
                  ((p256_05 >> 1) ^ (p256_05 << 2) ^ ((p256_05 << 8) | (p256_05 >> 24)) ^ ((p256_05 << 23) | (p256_05 >> 9))) + 
                  ((p256_06 >> 2) ^ (p256_06 << 1) ^ ((p256_06 << 12) | (p256_06 >> 20)) ^ ((p256_06 << 25) | (p256_06 >> 7))) + 
                  ((p256_07 >> 2) ^ (p256_07 << 2) ^ ((p256_07 << 15) | (p256_07 >> 17)) ^ ((p256_07 << 29) | (p256_07 >> 3))) + 
                  ((p256_08 >> 1) ^ (p256_08 << 3) ^ ((p256_08 << 4) | (p256_08 >> 28)) ^ ((p256_08 << 19) | (p256_08 >> 13))) + 
                  ((p256_09 >> 1) ^ (p256_09 << 2) ^ ((p256_09 << 8) | (p256_09 >> 24)) ^ ((p256_09 << 23) | (p256_09 >> 9))) + 
                  ((p256_10 >> 2) ^ (p256_10 << 1) ^ ((p256_10 << 12) | (p256_10 >> 20)) ^ ((p256_10 << 25) | (p256_10 >> 7))) + 
                  ((p256_11 >> 2) ^ (p256_11 << 2) ^ ((p256_11 << 15) | (p256_11 >> 17)) ^ ((p256_11 << 29) | (p256_11 >> 3))) + 
                  ((p256_12 >> 1) ^ (p256_12 << 3) ^ ((p256_12 << 4) | (p256_12 >> 28)) ^ ((p256_12 << 19) | (p256_12 >> 13))) + 
                  ((p256_13 >> 1) ^ (p256_13 << 2) ^ ((p256_13 << 8) | (p256_13 >> 24)) ^ ((p256_13 << 23) | (p256_13 >> 9))) + 
                  ((p256_14 >> 2) ^ (p256_14 << 1) ^ ((p256_14 << 12) | (p256_14 >> 20)) ^ ((p256_14 << 25) | (p256_14 >> 7))) + 
                  ((p256_15 >> 2) ^ (p256_15 << 2) ^ ((p256_15 << 15) | (p256_15 >> 17)) ^ ((p256_15 << 29) | (p256_15 >> 3))) + 
                  ((p256_16 >> 1) ^ (p256_16 << 3) ^ ((p256_16 << 4) | (p256_16 >> 28)) ^ ((p256_16 << 19) | (p256_16 >> 13))) + 
                  ((td32_01 + td32_04 - td32_11 + 0x5aaaaaa5) ^ 0xaaaaaaa8);

        XL32 ^= p256_17;
        uint TempEven32 = p256_14 + p256_12 + p256_10 + p256_08 + p256_06 + p256_04 + p256_02;
        uint TempOdd32 = p256_15 + p256_13 + p256_11 + p256_09 + p256_07 + p256_05 + p256_03;

        p256_18 = TempEven32 + 
                  ((p256_03 << 3) | (p256_03 >> 29)) + 
                  ((p256_05 << 7) | (p256_05 >> 25)) + 
                  ((p256_07 << 13) | (p256_07 >> 19)) + 
                  ((p256_09 << 16) | (p256_09 >> 16)) + 
                  ((p256_11 << 19) | (p256_11 >> 13)) + 
                  ((p256_13 << 23) | (p256_13 >> 9)) + 
                  ((p256_15 << 27) | (p256_15 >> 5)) + 
                  ((p256_16 >> 1) ^ p256_16) + 
                  ((p256_17 >> 2) ^ p256_17) + 
                  ((td32_02 + td32_05 - td32_12 + 0x5ffffffa) ^ 0xaaaaaaa9);

        XL32 ^= p256_18;

        p256_19 = TempOdd32 + 
                  ((p256_04 << 3) | (p256_04 >> 29)) + 
                  ((p256_06 << 7) | (p256_06 >> 25)) + 
                  ((p256_08 << 13) | (p256_08 >> 19)) + ((p256_10 << 16) | (p256_10 >> 16)) + 
                  ((p256_12 << 19) | (p256_12 >> 13)) + ((p256_14 << 23) | (p256_14 >> 9)) + 
                  ((p256_16 << 27) | (p256_16 >> 5)) + ((p256_17 >> 1) ^ p256_17) + ((p256_18 >> 2) ^ p256_18) + 
                  ((td32_03 + td32_06 - td32_13 + 0x6555554f) ^ 0xaaaaaaaa);

        XL32 ^= p256_19;
        TempEven32 = TempEven32 + p256_16 - p256_02;

        p256_20 = TempEven32 + 
                  ((p256_05 << 3) | (p256_05 >> 29)) + 
                  ((p256_07 << 7) | (p256_07 >> 25)) + 
                  ((p256_09 << 13) | (p256_09 >> 19)) + 
                  ((p256_11 << 16) | (p256_11 >> 16)) + 
                  ((p256_13 << 19) | (p256_13 >> 13)) + 
                  ((p256_15 << 23) | (p256_15 >> 9)) + 
                  ((p256_17 << 27) | (p256_17 >> 5)) + 
                  ((p256_18 >> 1) ^ p256_18) + 
                  ((p256_19 >> 2) ^ p256_19) + 
                  ((td32_04 + td32_07 - td32_14 + 0x6aaaaaa4) ^ 0xaaaaaaab);

        XL32 ^= p256_20;
        TempOdd32 = TempOdd32 + p256_17 - p256_03;

        p256_21 = TempOdd32 + 
                  ((p256_06 << 3) | (p256_06 >> 29)) + 
                  ((p256_08 << 7) | (p256_08 >> 25)) + 
                  ((p256_10 << 13) | (p256_10 >> 19)) + 
                  ((p256_12 << 16) | (p256_12 >> 16)) + 
                  ((p256_14 << 19) | (p256_14 >> 13)) + 
                  ((p256_16 << 23) | (p256_16 >> 9)) + 
                  ((p256_18 << 27) | (p256_18 >> 5)) + 
                  ((p256_19 >> 1) ^ p256_19) + 
                  ((p256_20 >> 2) ^ p256_20) + 
                  ((td32_05 + td32_08 - td32_15 + 0x6ffffff9) ^ 0xaaaaaaac);

        XL32 ^= p256_21;
        TempEven32 = TempEven32 + p256_18 - p256_04;

        p256_22 = TempEven32 + 
                  ((p256_07 << 3) | (p256_07 >> 29)) + 
                  ((p256_09 << 7) | (p256_09 >> 25)) + 
                  ((p256_11 << 13) | (p256_11 >> 19)) + 
                  ((p256_13 << 16) | (p256_13 >> 16)) + 
                  ((p256_15 << 19) | (p256_15 >> 13)) + 
                  ((p256_17 << 23) | (p256_17 >> 9)) + 
                  ((p256_19 << 27) | (p256_19 >> 5)) + 
                  ((p256_20 >> 1) ^ p256_20) + 
                  ((p256_21 >> 2) ^ p256_21) + 
                  ((td32_06 + td32_09 - td32_00 + 0x7555554e) ^ 0xaaaaaaad);

        XL32 ^= p256_22;
        TempOdd32 = TempOdd32 + p256_19 - p256_05;

        p256_23 = TempOdd32 + 
                  ((p256_08 << 3) | (p256_08 >> 29)) + 
                  ((p256_10 << 7) | (p256_10 >> 25)) + 
                  ((p256_12 << 13) | (p256_12 >> 19)) + 
                  ((p256_14 << 16) | (p256_14 >> 16)) + 
                  ((p256_16 << 19) | (p256_16 >> 13)) + 
                  ((p256_18 << 23) | (p256_18 >> 9)) + 
                  ((p256_20 << 27) | (p256_20 >> 5)) + 
                  ((p256_21 >> 1) ^ p256_21) + 
                  ((p256_22 >> 2) ^ p256_22) + 
                  ((td32_07 + td32_10 - td32_01 + 0x7aaaaaa3) ^ 0xaaaaaaae);

        XL32 ^= p256_23;
        TempEven32 = TempEven32 + p256_20 - p256_06;

        p256_24 = TempEven32 + 
                  ((p256_09 << 3) | (p256_09 >> 29)) + 
                  ((p256_11 << 7) | (p256_11 >> 25)) + 
                  ((p256_13 << 13) | (p256_13 >> 19)) + 
                  ((p256_15 << 16) | (p256_15 >> 16)) + 
                  ((p256_17 << 19) | (p256_17 >> 13)) + 
                  ((p256_19 << 23) | (p256_19 >> 9)) + 
                  ((p256_21 << 27) | (p256_21 >> 5)) + 
                  ((p256_22 >> 1) ^ p256_22) + 
                  ((p256_23 >> 2) ^ p256_23) + 
                  ((td32_08 + td32_11 - td32_02 + 0x7ffffff8) ^ 0xaaaaaaaf);

        uint XH32 = XL32 ^ p256_24;
        TempOdd32 = TempOdd32 + p256_21 - p256_07;

        p256_25 = TempOdd32 + 
                  ((p256_10 << 3) | (p256_10 >> 29)) + 
                  ((p256_12 << 7) | (p256_12 >> 25)) + 
                  ((p256_14 << 13) | (p256_14 >> 19)) + 
                  ((p256_16 << 16) | (p256_16 >> 16)) + 
                  ((p256_18 << 19) | (p256_18 >> 13)) + 
                  ((p256_20 << 23) | (p256_20 >> 9)) + 
                  ((p256_22 << 27) | (p256_22 >> 5)) + 
                  ((p256_23 >> 1) ^ p256_23) + 
                  ((p256_24 >> 2) ^ p256_24) + 
                  ((td32_09 + td32_12 - td32_03 + 0x8555554d) ^ 0xaaaaaaa0);

        XH32 ^= p256_25;
        TempEven32 = TempEven32 + p256_22 - p256_08;

        p256_26 = TempEven32 + 
                  ((p256_11 << 3) | (p256_11 >> 29)) + 
                  ((p256_13 << 7) | (p256_13 >> 25)) + 
                  ((p256_15 << 13) | (p256_15 >> 19)) + 
                  ((p256_17 << 16) | (p256_17 >> 16)) + 
                  ((p256_19 << 19) | (p256_19 >> 13)) + 
                  ((p256_21 << 23) | (p256_21 >> 9)) + 
                  ((p256_23 << 27) | (p256_23 >> 5)) + 
                  ((p256_24 >> 1) ^ p256_24) + 
                  ((p256_25 >> 2) ^ p256_25) + 
                  ((td32_10 + td32_13 - td32_04 + 0x8aaaaaa2) ^ 0xaaaaaaa1);

        XH32 ^= p256_26;
        TempOdd32 = TempOdd32 + p256_23 - p256_09;

        p256_27 = TempOdd32 + 
                  ((p256_12 << 3) | (p256_12 >> 29)) + 
                  ((p256_14 << 7) | (p256_14 >> 25)) + 
                  ((p256_16 << 13) | (p256_16 >> 19)) + 
                  ((p256_18 << 16) | (p256_18 >> 16)) + 
                  ((p256_20 << 19) | (p256_20 >> 13)) + 
                  ((p256_22 << 23) | (p256_22 >> 9)) + 
                  ((p256_24 << 27) | (p256_24 >> 5)) + 
                  ((p256_25 >> 1) ^ p256_25) + 
                  ((p256_26 >> 2) ^ p256_26) + 
                  ((td32_11 + td32_14 - td32_05 + 0x8ffffff7) ^ 0xaaaaaaa2);

        XH32 ^= p256_27;
        TempEven32 = TempEven32 + p256_24 - p256_10;

        p256_28 = TempEven32 + 
                  ((p256_13 << 3) | (p256_13 >> 29)) + 
                  ((p256_15 << 7) | (p256_15 >> 25)) + 
                  ((p256_17 << 13) | (p256_17 >> 19)) + 
                  ((p256_19 << 16) | (p256_19 >> 16)) + 
                  ((p256_21 << 19) | (p256_21 >> 13)) + 
                  ((p256_23 << 23) | (p256_23 >> 9)) + 
                  ((p256_25 << 27) | (p256_25 >> 5)) + 
                  ((p256_26 >> 1) ^ p256_26) + 
                  ((p256_27 >> 2) ^ p256_27) + 
                  ((td32_12 + td32_15 - td32_06 + 0x9555554c) ^ 0xaaaaaaa3);

        XH32 ^= p256_28;
        TempOdd32 = TempOdd32 + p256_25 - p256_11;

        p256_29 = TempOdd32 + 
                  ((p256_14 << 3) | (p256_14 >> 29)) + 
                  ((p256_16 << 7) | (p256_16 >> 25)) + 
                  ((p256_18 << 13) | (p256_18 >> 19)) + 
                  ((p256_20 << 16) | (p256_20 >> 16)) + 
                  ((p256_22 << 19) | (p256_22 >> 13)) + 
                  ((p256_24 << 23) | (p256_24 >> 9)) + 
                  ((p256_26 << 27) | (p256_26 >> 5)) + 
                  ((p256_27 >> 1) ^ p256_27) + 
                  ((p256_28 >> 2) ^ p256_28) + 
                  ((td32_13 + td32_00 - td32_07 + 0x9aaaaaa1) ^ 0xaaaaaaa4);

        XH32 ^= p256_29;
        TempEven32 = TempEven32 + p256_26 - p256_12;

        p256_30 = TempEven32 + 
                  ((p256_15 << 3) | (p256_15 >> 29)) + 
                  ((p256_17 << 7) | (p256_17 >> 25)) + 
                  ((p256_19 << 13) | (p256_19 >> 19)) + 
                  ((p256_21 << 16) | (p256_21 >> 16)) + 
                  ((p256_23 << 19) | (p256_23 >> 13)) + 
                  ((p256_25 << 23) | (p256_25 >> 9)) + 
                  ((p256_27 << 27) | (p256_27 >> 5)) + 
                  ((p256_28 >> 1) ^ p256_28) + 
                  ((p256_29 >> 2) ^ p256_29) + 
                  ((td32_14 + td32_01 - td32_08 + 0x9ffffff6) ^ 0xaaaaaaa5);

        XH32 ^= p256_30;
        TempOdd32 = TempOdd32 + p256_27 - p256_13;

        p256_31 = TempOdd32 + 
                  ((p256_16 << 3) | (p256_16 >> 29)) + 
                  ((p256_18 << 7) | (p256_18 >> 25)) + 
                  ((p256_20 << 13) | (p256_20 >> 19)) + 
                  ((p256_22 << 16) | (p256_22 >> 16)) + 
                  ((p256_24 << 19) | (p256_24 >> 13)) + 
                  ((p256_26 << 23) | (p256_26 >> 9)) + 
                  ((p256_28 << 27) | (p256_28 >> 5)) + 
                  ((p256_29 >> 1) ^ p256_29) + 
                  ((p256_30 >> 2) ^ p256_30) + 
                  ((td32_15 + td32_02 - td32_09 + 0xa555554b) ^ 0xaaaaaaa6);

        XH32 ^= p256_31;

        m_state[0] = ((XH32 << 5) ^ (p256_16 >> 5) ^ m_state[0]) + ( XL32 ^ p256_24 ^ p256_00);
        m_state[1] = ((XH32 >> 7) ^ (p256_17 << 8) ^ m_state[1]) + ( XL32 ^ p256_25 ^ p256_01);
        m_state[2] = ((XH32 >> 5) ^ (p256_18 << 5) ^ m_state[2]) + ( XL32 ^ p256_26 ^ p256_02);
        m_state[3] = ((XH32 >> 1) ^ (p256_19 << 5) ^ m_state[3]) + ( XL32 ^ p256_27 ^ p256_03);
        m_state[4] = ((XH32 >> 3) ^ p256_20 ^ m_state[4]) + ( XL32 ^ p256_28 ^ p256_04);
        m_state[5] = ((XH32 << 6) ^ (p256_21 >> 6) ^ m_state[5]) + ( XL32 ^ p256_29 ^ p256_05);
        m_state[6] = ((XH32 >> 4) ^ (p256_22 << 6) ^ m_state[6]) + ( XL32 ^ p256_30 ^ p256_06);
        m_state[7] = ((XH32 >> 11) ^ (p256_23 << 2) ^ m_state[7]) + ( XL32 ^ p256_31 ^ p256_07);

        m_state[8] = ((m_state[4] << 9) | (m_state[4] >> 23)) + ( XH32 ^ p256_24 ^ m_state[8]) + ((XL32 << 8) ^ p256_23 ^ p256_08);
        m_state[9] = ((m_state[5] << 10) | (m_state[5] >> 22)) + ( XH32 ^ p256_25 ^ m_state[9]) + ((XL32 >> 6) ^ p256_16 ^ p256_09);
        m_state[10] = ((m_state[6] << 11) | (m_state[6] >> 21)) + ( XH32 ^ p256_26 ^ m_state[10]) + ((XL32 << 6) ^ p256_17 ^ p256_10);
        m_state[11] = ((m_state[7] << 12) | (m_state[7] >> 20)) + ( XH32 ^ p256_27 ^ m_state[11]) + ((XL32 << 4) ^ p256_18 ^ p256_11);
        m_state[12] = ((m_state[0] << 13) | (m_state[0] >> 19)) + ( XH32 ^ p256_28 ^ m_state[12]) + ((XL32 >> 3) ^ p256_19 ^ p256_12);
        m_state[13] = ((m_state[1] << 14) | (m_state[1] >> 18)) + ( XH32 ^ p256_29 ^ m_state[13]) + ((XL32 >> 4) ^ p256_20 ^ p256_13);
        m_state[14] = ((m_state[2] << 15) | (m_state[2] >> 17)) + ( XH32 ^ p256_30 ^ m_state[14]) + ((XL32 >> 7) ^ p256_21 ^ p256_14);
        m_state[15] = ((m_state[3] << 16) | (m_state[3] >> 16)) + ( XH32 ^ p256_31 ^ m_state[15]) + ((XL32 >> 2) ^ p256_22 ^ p256_15);
    }

    void BMW512Base::TransformBlock(byte* a_data, int a_index)
    {
        ulong* data64 = (ulong*)(a_data + a_index);
        ulong* tp512 = m_state; 
        ulong* tdat64 = data64;

        ulong p512_00 = (*tp512++) ^ (*tdat64++);
        ulong p512_01 = (*tp512++) ^ (*tdat64++);
        ulong p512_02 = (*tp512++) ^ (*tdat64++);
        ulong p512_03 = (*tp512++) ^ (*tdat64++);
        ulong p512_04 = (*tp512++) ^ (*tdat64++);
        ulong p512_05 = (*tp512++) ^ (*tdat64++);
        ulong p512_06 = (*tp512++) ^ (*tdat64++);
        ulong p512_07 = (*tp512++) ^ (*tdat64++);
        ulong p512_08 = (*tp512++) ^ (*tdat64++);
        ulong p512_09 = (*tp512++) ^ (*tdat64++);
        ulong p512_10 = (*tp512++) ^ (*tdat64++);
        ulong p512_11 = (*tp512++) ^ (*tdat64++);
        ulong p512_12 = (*tp512++) ^ (*tdat64++);
        ulong p512_13 = (*tp512++) ^ (*tdat64++);
        ulong p512_14 = (*tp512++) ^ (*tdat64++);
        ulong p512_15 = (*tp512++) ^ (*tdat64++);

        ulong td64_00 = (data64[0] << 1) | (data64[0] >> 63);
        ulong td64_01 = (data64[1] << 2) | (data64[1] >> 62);
        ulong td64_02 = (data64[2] << 3) | (data64[2] >> 61);
        ulong td64_03 = (data64[3] << 4) | (data64[3] >> 60);
        ulong td64_04 = (data64[4] << 5) | (data64[4] >> 59);
        ulong td64_05 = (data64[5] << 6) | (data64[5] >> 58);
        ulong td64_06 = (data64[6] << 7) | (data64[6] >> 57);
        ulong td64_07 = (data64[7] << 8) | (data64[7] >> 56);
        ulong td64_08 = (data64[8] << 9) | (data64[8] >> 55);
        ulong td64_09 = (data64[9] << 10) | (data64[9] >> 54);
        ulong td64_10 = (data64[10] << 11) | (data64[10] >> 53);
        ulong td64_11 = (data64[11] << 12) | (data64[11] >> 52);
        ulong td64_12 = (data64[12] << 13) | (data64[12] >> 51);
        ulong td64_13 = (data64[13] << 14) | (data64[13] >> 50);
        ulong td64_14 = (data64[14] << 15) | (data64[14] >> 49);
        ulong td64_15 = (data64[15] << 16) | (data64[15] >> 48);

        ulong t512_16 = p512_01 - p512_14;
        ulong t512_17 = p512_15 - p512_12;
        ulong t512_18 = p512_14 - p512_07;
        ulong t512_19 = p512_13 - p512_06;
        ulong t512_20 = p512_08 - p512_05;
        ulong t512_21 = p512_08 - p512_01;

        ulong p512_16 = (p512_05 + t512_18 + p512_10 + p512_13);
        p512_16 = ((p512_16 >> 1) ^ (p512_16 << 3) ^ ((p512_16 << 4) | (p512_16 >> 60)) ^ ((p512_16 << 37) | (p512_16 >> 27))) + m_state[1];
        ulong p512_17 = (p512_06 - p512_08 + p512_11 + p512_14 - p512_15);
        p512_17 = ((p512_17 >> 1) ^ (p512_17 << 2) ^ ((p512_17 << 13) | (p512_17 >> 51)) ^ ((p512_17 << 43) | (p512_17 >> 21))) + m_state[2];
        ulong p512_18 = (p512_00 + p512_07 + p512_09 + t512_17);
        p512_18 = ((p512_18 >> 2) ^ (p512_18 << 1) ^ ((p512_18 << 19) | (p512_18 >> 45)) ^ ((p512_18 << 53) | (p512_18 >> 11))) + m_state[3];
        ulong p512_19 = (p512_00 + t512_21 - p512_10 + p512_13);
        p512_19 = ((p512_19 >> 2) ^ (p512_19 << 2) ^ ((p512_19 << 28) | (p512_19 >> 36)) ^ ((p512_19 << 59) | (p512_19 >> 5))) + m_state[4];
        ulong p512_20 = (t512_16 + p512_02 + p512_09 - p512_11);
        p512_20 = ((p512_20 >> 1) ^ p512_20) + m_state[5];
        ulong p512_21 = (p512_03 - p512_02 + p512_10 + t512_17);
        p512_21 = ((p512_21 >> 1) ^ (p512_21 << 3) ^ ((p512_21 << 4) | (p512_21 >> 60)) ^ ((p512_21 << 37) | (p512_21 >> 27))) + m_state[6];
        ulong p512_22 = (p512_04 - p512_00 - p512_03 - p512_11 + p512_13);
        p512_22 = ((p512_22 >> 1) ^ (p512_22 << 2) ^ ((p512_22 << 13) | (p512_22 >> 51)) ^ ((p512_22 << 43) | (p512_22 >> 21))) + m_state[7];
        ulong p512_23 = (t512_16 - p512_04 - p512_05 - p512_12);
        p512_23 = ((p512_23 >> 2) ^ (p512_23 << 1) ^ ((p512_23 << 19) | (p512_23 >> 45)) ^ ((p512_23 << 53) | (p512_23 >> 11))) + m_state[8];
        ulong p512_24 = (p512_02 - p512_05 + t512_19 - p512_15);
        p512_24 = ((p512_24 >> 2) ^ (p512_24 << 2) ^ ((p512_24 << 28) | (p512_24 >> 36)) ^ ((p512_24 << 59) | (p512_24 >> 5))) + m_state[9];
        ulong p512_25 = (p512_00 - p512_03 + p512_06 + t512_18);
        p512_25 = ((p512_25 >> 1) ^ p512_25) + m_state[10];
        ulong p512_26 = (t512_21 - p512_04 - p512_07 + p512_15);
        p512_26 = ((p512_26 >> 1) ^ (p512_26 << 3) ^ ((p512_26 << 4) | (p512_26 >> 60)) ^ ((p512_26 << 37) | (p512_26 >> 27))) + m_state[11];
        ulong p512_27 = (t512_20 - p512_00 - p512_02 + p512_09);
        p512_27 = ((p512_27 >> 1) ^ (p512_27 << 2) ^ ((p512_27 << 13) | (p512_27 >> 51)) ^ ((p512_27 << 43) | (p512_27 >> 21))) + m_state[12];
        ulong p512_28 = (p512_01 + p512_03 - p512_06 - p512_09 + p512_10);
        p512_28 = ((p512_28 >> 2) ^ (p512_28 << 1) ^ ((p512_28 << 19) | (p512_28 >> 45)) ^ ((p512_28 << 53) | (p512_28 >> 11))) + m_state[13];
        ulong p512_29 = (p512_02 + p512_04 + p512_07 + p512_10 + p512_11);
        p512_29 = ((p512_29 >> 2) ^ (p512_29 << 2) ^ ((p512_29 << 28) | (p512_29 >> 36)) ^ ((p512_29 << 59) | (p512_29 >> 5))) + m_state[14];
        ulong p512_30 = (p512_03 + t512_20 - p512_11 - p512_12);
        p512_14 = ((p512_30 >> 1) ^ p512_30) + m_state[15];
        ulong p512_31 = (p512_12 - p512_04 + t512_19 - p512_09);
        p512_15 = ((p512_31 >> 1) ^ (p512_31 << 3) ^ ((p512_31 << 4) | (p512_31 >> 60)) ^ ((p512_31 << 37) | (p512_31 >> 27))) + m_state[0];

        p512_00 = p512_16;
        p512_01 = p512_17;
        p512_02 = p512_18;
        p512_03 = p512_19;
        p512_04 = p512_20;
        p512_05 = p512_21;
        p512_06 = p512_22;
        p512_07 = p512_23;
        p512_08 = p512_24;
        p512_09 = p512_25;
        p512_10 = p512_26;
        p512_11 = p512_27;
        p512_12 = p512_28;
        p512_13 = p512_29;

        p512_16 = ((p512_00 >> 1) ^ (p512_00 << 2) ^ ((p512_00 << 13) | (p512_00 >> 51)) ^ ((p512_00 << 43) | (p512_00 >> 21))) + 
                  ((p512_01 >> 2) ^ (p512_01 << 1) ^ ((p512_01 << 19) | (p512_01 >> 45)) ^ ((p512_01 << 53) | (p512_01 >> 11))) + 
                  ((p512_02 >> 2) ^ (p512_02 << 2) ^ ((p512_02 << 28) | (p512_02 >> 36)) ^ ((p512_02 << 59) | (p512_02 >> 5))) + 
                  ((p512_03 >> 1) ^ (p512_03 << 3) ^ ((p512_03 << 4) | (p512_03 >> 60)) ^ ((p512_03 << 37) | (p512_03 >> 27))) + 
                  ((p512_04 >> 1) ^ (p512_04 << 2) ^ ((p512_04 << 13) | (p512_04 >> 51)) ^ ((p512_04 << 43) | (p512_04 >> 21))) + 
                  ((p512_05 >> 2) ^ (p512_05 << 1) ^ ((p512_05 << 19) | (p512_05 >> 45)) ^ ((p512_05 << 53) | (p512_05 >> 11))) + 
                  ((p512_06 >> 2) ^ (p512_06 << 2) ^ ((p512_06 << 28) | (p512_06 >> 36)) ^ ((p512_06 << 59) | (p512_06 >> 5))) + 
                  ((p512_07 >> 1) ^ (p512_07 << 3) ^ ((p512_07 << 4) | (p512_07 >> 60)) ^ ((p512_07 << 37) | (p512_07 >> 27))) + 
                  ((p512_08 >> 1) ^ (p512_08 << 2) ^ ((p512_08 << 13) | (p512_08 >> 51)) ^ ((p512_08 << 43) | (p512_08 >> 21))) + 
                  ((p512_09 >> 2) ^ (p512_09 << 1) ^ ((p512_09 << 19) | (p512_09 >> 45)) ^ ((p512_09 << 53) | (p512_09 >> 11))) + 
                  ((p512_10 >> 2) ^ (p512_10 << 2) ^ ((p512_10 << 28) | (p512_10 >> 36)) ^ ((p512_10 << 59) | (p512_10 >> 5))) + 
                  ((p512_11 >> 1) ^ (p512_11 << 3) ^ ((p512_11 << 4) | (p512_11 >> 60)) ^ ((p512_11 << 37) | (p512_11 >> 27))) + 
                  ((p512_12 >> 1) ^ (p512_12 << 2) ^ ((p512_12 << 13) | (p512_12 >> 51)) ^ ((p512_12 << 43) | (p512_12 >> 21))) + 
                  ((p512_13 >> 2) ^ (p512_13 << 1) ^ ((p512_13 << 19) | (p512_13 >> 45)) ^ ((p512_13 << 53) | (p512_13 >> 11))) + 
                  ((p512_14 >> 2) ^ (p512_14 << 2) ^ ((p512_14 << 28) | (p512_14 >> 36)) ^ ((p512_14 << 59) | (p512_14 >> 5))) + 
                  ((p512_15 >> 1) ^ (p512_15 << 3) ^ ((p512_15 << 4) | (p512_15 >> 60)) ^ ((p512_15 << 37) | (p512_15 >> 27))) + 
                  ((td64_00 + td64_03 - td64_10 + 0x5555555555555550) ^ m_state[7]);

        ulong XL64 = p512_16;

        p512_17 = ((p512_01 >> 1) ^ (p512_01 << 2) ^ ((p512_01 << 13) | (p512_01 >> 51)) ^ ((p512_01 << 43) | (p512_01 >> 21))) + 
                  ((p512_02 >> 2) ^ (p512_02 << 1) ^ ((p512_02 << 19) | (p512_02 >> 45)) ^ ((p512_02 << 53) | (p512_02 >> 11))) + 
                  ((p512_03 >> 2) ^ (p512_03 << 2) ^ ((p512_03 << 28) | (p512_03 >> 36)) ^ ((p512_03 << 59) | (p512_03 >> 5))) + 
                  ((p512_04 >> 1) ^ (p512_04 << 3) ^ ((p512_04 << 4) | (p512_04 >> 60)) ^ ((p512_04 << 37) | (p512_04 >> 27))) + 
                  ((p512_05 >> 1) ^ (p512_05 << 2) ^ ((p512_05 << 13) | (p512_05 >> 51)) ^ ((p512_05 << 43) | (p512_05 >> 21))) + 
                  ((p512_06 >> 2) ^ (p512_06 << 1) ^ ((p512_06 << 19) | (p512_06 >> 45)) ^ ((p512_06 << 53) | (p512_06 >> 11))) + 
                  ((p512_07 >> 2) ^ (p512_07 << 2) ^ ((p512_07 << 28) | (p512_07 >> 36)) ^ ((p512_07 << 59) | (p512_07 >> 5))) + 
                  ((p512_08 >> 1) ^ (p512_08 << 3) ^ ((p512_08 << 4) | (p512_08 >> 60)) ^ ((p512_08 << 37) | (p512_08 >> 27))) + 
                  ((p512_09 >> 1) ^ (p512_09 << 2) ^ ((p512_09 << 13) | (p512_09 >> 51)) ^ ((p512_09 << 43) | (p512_09 >> 21))) + 
                  ((p512_10 >> 2) ^ (p512_10 << 1) ^ ((p512_10 << 19) | (p512_10 >> 45)) ^ ((p512_10 << 53) | (p512_10 >> 11))) + 
                  ((p512_11 >> 2) ^ (p512_11 << 2) ^ ((p512_11 << 28) | (p512_11 >> 36)) ^ ((p512_11 << 59) | (p512_11 >> 5))) + 
                  ((p512_12 >> 1) ^ (p512_12 << 3) ^ ((p512_12 << 4) | (p512_12 >> 60)) ^ ((p512_12 << 37) | (p512_12 >> 27))) + 
                  ((p512_13 >> 1) ^ (p512_13 << 2) ^ ((p512_13 << 13) | (p512_13 >> 51)) ^ ((p512_13 << 43) | (p512_13 >> 21))) + 
                  ((p512_14 >> 2) ^ (p512_14 << 1) ^ ((p512_14 << 19) | (p512_14 >> 45)) ^ ((p512_14 << 53) | (p512_14 >> 11))) + 
                  ((p512_15 >> 2) ^ (p512_15 << 2) ^ ((p512_15 << 28) | (p512_15 >> 36)) ^ ((p512_15 << 59) | (p512_15 >> 5))) + 
                  ((p512_16 >> 1) ^ (p512_16 << 3) ^ ((p512_16 << 4) | (p512_16 >> 60)) ^ ((p512_16 << 37) | (p512_16 >> 27))) + 
                  ((td64_01 + td64_04 - td64_11 + 0x5aaaaaaaaaaaaaa5) ^ m_state[8]);

        XL64 ^= p512_17;
        ulong TempEven64 = p512_14 + p512_12 + p512_10 + p512_08 + p512_06 + p512_04 + p512_02;
        ulong TempOdd64 = p512_15 + p512_13 + p512_11 + p512_09 + p512_07 + p512_05 + p512_03;

        p512_18 = TempEven64 + 
                  ((p512_03 << 5) | (p512_03 >> 59)) + 
                  ((p512_05 << 11) | (p512_05 >> 53)) + 
                  ((p512_07 << 27) | (p512_07 >> 37)) + 
                  ((p512_09 << 32) | (p512_09 >> 32)) + 
                  ((p512_11 << 37) | (p512_11 >> 27)) + 
                  ((p512_13 << 43) | (p512_13 >> 21)) + 
                  ((p512_15 << 53) | (p512_15 >> 11)) + 
                  ((p512_16 >> 1) ^ p512_16) + 
                  ((p512_17 >> 2) ^ p512_17) + 
                  ((td64_02 + td64_05 - td64_12 + 0x5ffffffffffffffa) ^ m_state[9]);

        XL64 ^= p512_18;

        p512_19 = TempOdd64 + 
                  ((p512_04 << 5) | (p512_04 >> 59)) + 
                  ((p512_06 << 11) | (p512_06 >> 53)) + 
                  ((p512_08 << 27) | (p512_08 >> 37)) + 
                  ((p512_10 << 32) | (p512_10 >> 32)) + 
                  ((p512_12 << 37) | (p512_12 >> 27)) + 
                  ((p512_14 << 43) | (p512_14 >> 21)) + 
                  ((p512_16 << 53) | (p512_16 >> 11)) + 
                  ((p512_17 >> 1) ^ p512_17) + 
                  ((p512_18 >> 2) ^ p512_18) + 
                  ((td64_03 + td64_06 - td64_13 + 0x655555555555554f) ^ m_state[10]);
        
        XL64 ^= p512_19;
        TempEven64 = TempEven64 + p512_16 - p512_02;

        p512_20 = TempEven64 + 
                  ((p512_05 << 5) | (p512_05 >> 59)) + 
                  ((p512_07 << 11) | (p512_07 >> 53)) + 
                  ((p512_09 << 27) | (p512_09 >> 37)) + 
                  ((p512_11 << 32) | (p512_11 >> 32)) + 
                  ((p512_13 << 37) | (p512_13 >> 27)) + 
                  ((p512_15 << 43) | (p512_15 >> 21)) + 
                  ((p512_17 << 53) | (p512_17 >> 11)) + 
                  ((p512_18 >> 1) ^ p512_18) + 
                  ((p512_19 >> 2) ^ p512_19) + 
                  ((td64_04 + td64_07 - td64_14 + 0x6aaaaaaaaaaaaaa4) ^ m_state[11]);
        
        XL64 ^= p512_20;
        TempOdd64 = TempOdd64 + p512_17 - p512_03;

        p512_21 = TempOdd64 + 
                  ((p512_06 << 5) | (p512_06 >> 59)) + 
                  ((p512_08 << 11) | (p512_08 >> 53)) + 
                  ((p512_10 << 27) | (p512_10 >> 37)) + 
                  ((p512_12 << 32) | (p512_12 >> 32)) + 
                  ((p512_14 << 37) | (p512_14 >> 27)) + 
                  ((p512_16 << 43) | (p512_16 >> 21)) + 
                  ((p512_18 << 53) | (p512_18 >> 11)) + 
                  ((p512_19 >> 1) ^ p512_19) + 
                  ((p512_20 >> 2) ^ p512_20) + 
                  ((td64_05 + td64_08 - td64_15 + 0x6ffffffffffffff9) ^ m_state[12]);

        XL64 ^= p512_21;
        TempEven64 += p512_18; TempEven64 -= p512_04;

        p512_22 = TempEven64 + 
                  ((p512_07 << 5) | (p512_07 >> 59)) + 
                  ((p512_09 << 11) | (p512_09 >> 53)) + 
                  ((p512_11 << 27) | (p512_11 >> 37)) + 
                  ((p512_13 << 32) | (p512_13 >> 32)) + 
                  ((p512_15 << 37) | (p512_15 >> 27)) + 
                  ((p512_17 << 43) | (p512_17 >> 21)) + 
                  ((p512_19 << 53) | (p512_19 >> 11)) + 
                  ((p512_20 >> 1) ^ p512_20) + 
                  ((p512_21 >> 2) ^ p512_21) + 
                  ((td64_06 + td64_09 - td64_00 + 0x755555555555554e) ^ m_state[13]);

        XL64 ^= p512_22;
        TempOdd64 += p512_19; TempOdd64 -= p512_05;

        p512_23 = TempOdd64 + 
                  ((p512_08 << 5) | (p512_08 >> 59)) + 
                  ((p512_10 << 11) | (p512_10 >> 53)) + 
                  ((p512_12 << 27) | (p512_12 >> 37)) + 
                  ((p512_14 << 32) | (p512_14 >> 32)) + 
                  ((p512_16 << 37) | (p512_16 >> 27)) + 
                  ((p512_18 << 43) | (p512_18 >> 21)) + 
                  ((p512_20 << 53) | (p512_20 >> 11)) + 
                  ((p512_21 >> 1) ^ p512_21) + 
                  ((p512_22 >> 2) ^ p512_22) + 
                  ((td64_07 + td64_10 - td64_01 + 0x7aaaaaaaaaaaaaa3) ^ m_state[14]);

        XL64 ^= p512_23;
        TempEven64 += p512_20; TempEven64 -= p512_06;
        
        p512_24 = TempEven64 + 
                  ((p512_09 << 5) | (p512_09 >> 59)) + 
                  ((p512_11 << 11) | (p512_11 >> 53)) + 
                  ((p512_13 << 27) | (p512_13 >> 37)) + 
                  ((p512_15 << 32) | (p512_15 >> 32)) + 
                  ((p512_17 << 37) | (p512_17 >> 27)) + 
                  ((p512_19 << 43) | (p512_19 >> 21)) + 
                  ((p512_21 << 53) | (p512_21 >> 11)) + 
                  ((p512_22 >> 1) ^ p512_22) + 
                  ((p512_23 >> 2) ^ p512_23) + 
                  ((td64_08 + td64_11 - td64_02 + 0x7ffffffffffffff8) ^ m_state[15]);

        ulong XH64 = XL64 ^ p512_24;
        TempOdd64 += p512_21; TempOdd64 -= p512_07;

        p512_25 = TempOdd64 + 
                  ((p512_10 << 5) | (p512_10 >> 59)) + 
                  ((p512_12 << 11) | (p512_12 >> 53)) + 
                  ((p512_14 << 27) | (p512_14 >> 37)) + 
                  ((p512_16 << 32) | (p512_16 >> 32)) + 
                  ((p512_18 << 37) | (p512_18 >> 27)) + 
                  ((p512_20 << 43) | (p512_20 >> 21)) + 
                  ((p512_22 << 53) | (p512_22 >> 11)) + 
                  ((p512_23 >> 1) ^ p512_23) + 
                  ((p512_24 >> 2) ^ p512_24) + 
                  ((td64_09 + td64_12 - td64_03 + 0x855555555555554d) ^ m_state[0]);

        XH64 ^= p512_25;
        TempEven64 += p512_22; TempEven64 -= p512_08;

        p512_26 = TempEven64 + 
                  ((p512_11 << 5) | (p512_11 >> 59)) + 
                  ((p512_13 << 11) | (p512_13 >> 53)) + 
                  ((p512_15 << 27) | (p512_15 >> 37)) + 
                  ((p512_17 << 32) | (p512_17 >> 32)) + 
                  ((p512_19 << 37) | (p512_19 >> 27)) + 
                  ((p512_21 << 43) | (p512_21 >> 21)) + 
                  ((p512_23 << 53) | (p512_23 >> 11)) + 
                  ((p512_24 >> 1) ^ p512_24) + 
                  ((p512_25 >> 2) ^ p512_25) + 
                  ((td64_10 + td64_13 - td64_04 + 0x8aaaaaaaaaaaaaa2) ^ m_state[1]);
        
        XH64 ^= p512_26;
        TempOdd64 += p512_23; TempOdd64 -= p512_09;

        p512_27 = TempOdd64 + 
                  ((p512_12 << 5) | (p512_12 >> 59)) + 
                  ((p512_14 << 11) | (p512_14 >> 53)) + 
                  ((p512_16 << 27) | (p512_16 >> 37)) + 
                  ((p512_18 << 32) | (p512_18 >> 32)) + 
                  ((p512_20 << 37) | (p512_20 >> 27)) + 
                  ((p512_22 << 43) | (p512_22 >> 21)) + 
                  ((p512_24 << 53) | (p512_24 >> 11)) + 
                  ((p512_25 >> 1) ^ p512_25) + 
                  ((p512_26 >> 2) ^ p512_26) + 
                  ((td64_11 + td64_14 - td64_05 + 0x8ffffffffffffff7) ^ m_state[2]);
        
        XH64 ^= p512_27;
        TempEven64 += p512_24; TempEven64 -= p512_10;

        p512_28 = TempEven64 + 
                  ((p512_13 << 5) | (p512_13 >> 59)) + 
                  ((p512_15 << 11) | (p512_15 >> 53)) + 
                  ((p512_17 << 27) | (p512_17 >> 37)) + 
                  ((p512_19 << 32) | (p512_19 >> 32)) + 
                  ((p512_21 << 37) | (p512_21 >> 27)) + 
                  ((p512_23 << 43) | (p512_23 >> 21)) + 
                  ((p512_25 << 53) | (p512_25 >> 11)) + 
                  ((p512_26 >> 1) ^ p512_26) + 
                  ((p512_27 >> 2) ^ p512_27) + 
                  ((td64_12 + td64_15 - td64_06 + 0x955555555555554c) ^ m_state[3]);

        XH64 ^= p512_28;
        TempOdd64 += p512_25; TempOdd64 -= p512_11;

        p512_29 = TempOdd64 + 
                  ((p512_14 << 5) | (p512_14 >> 59)) + 
                  ((p512_16 << 11) | (p512_16 >> 53)) + 
                  ((p512_18 << 27) | (p512_18 >> 37)) + 
                  ((p512_20 << 32) | (p512_20 >> 32)) + 
                  ((p512_22 << 37) | (p512_22 >> 27)) + 
                  ((p512_24 << 43) | (p512_24 >> 21)) + 
                  ((p512_26 << 53) | (p512_26 >> 11)) + 
                  ((p512_27 >> 1) ^ p512_27) + 
                  ((p512_28 >> 2) ^ p512_28) + 
                  ((td64_13 + td64_00 - td64_07 + 0x9aaaaaaaaaaaaaa1) ^ m_state[4]);

        XH64 ^= p512_29;
        TempEven64 += p512_26; TempEven64 -= p512_12;

        p512_30 = TempEven64 + 
                  ((p512_15 << 5) | (p512_15 >> 59)) + 
                  ((p512_17 << 11) | (p512_17 >> 53)) + 
                  ((p512_19 << 27) | (p512_19 >> 37)) + 
                  ((p512_21 << 32) | (p512_21 >> 32)) + 
                  ((p512_23 << 37) | (p512_23 >> 27)) + 
                  ((p512_25 << 43) | (p512_25 >> 21)) + 
                  ((p512_27 << 53) | (p512_27 >> 11)) + 
                  ((p512_28 >> 1) ^ p512_28) + 
                  ((p512_29 >> 2) ^ p512_29) + 
                  ((td64_14 + td64_01 - td64_08 + 0x9ffffffffffffff6) ^ m_state[5]);
        
        XH64 ^= p512_30;
        TempOdd64 += p512_27; TempOdd64 -= p512_13;

        p512_31 = TempOdd64 + 
                  ((p512_16 << 5) | (p512_16 >> 59)) + 
                  ((p512_18 << 11) | (p512_18 >> 53)) + 
                  ((p512_20 << 27) | (p512_20 >> 37)) + 
                  ((p512_22 << 32) | (p512_22 >> 32)) + 
                  ((p512_24 << 37) | (p512_24 >> 27)) + 
                  ((p512_26 << 43) | (p512_26 >> 21)) + 
                  ((p512_28 << 53) | (p512_28 >> 11)) + 
                  ((p512_29 >> 1) ^ p512_29) + 
                  ((p512_30 >> 2) ^ p512_30) + 
                  ((td64_15 + td64_02 - td64_09 + 0xa55555555555554b) ^ m_state[6]);

        XH64 ^= p512_31;

        m_state[0] = ((XH64 << 5) ^ (p512_16 >> 5) ^ data64[0]) + ( XL64 ^ p512_24 ^ p512_00);
        m_state[1] = ((XH64 >> 7) ^ (p512_17 << 8) ^ data64[1]) + ( XL64 ^ p512_25 ^ p512_01);
        m_state[2] = ((XH64 >> 5) ^ (p512_18 << 5) ^ data64[2]) + ( XL64 ^ p512_26 ^ p512_02);
        m_state[3] = ((XH64 >> 1) ^ (p512_19 << 5) ^ data64[3]) + ( XL64 ^ p512_27 ^ p512_03);
        m_state[4] = ((XH64 >> 3) ^ p512_20 ^ data64[4]) + ( XL64 ^ p512_28 ^ p512_04);
        m_state[5] = ((XH64 << 6) ^ (p512_21 >> 6) ^ data64[5]) + ( XL64 ^ p512_29 ^ p512_05);
        m_state[6] = ((XH64 >> 4) ^ (p512_22 << 6) ^ data64[6]) + ( XL64 ^ p512_30 ^ p512_06);
        m_state[7] = ((XH64 >> 11) ^ (p512_23 << 2) ^ data64[7]) + ( XL64 ^ p512_31 ^ p512_07);

        m_state[8] = ((m_state[4] << 9) | (m_state[4] >> 55)) + ( XH64 ^ p512_24 ^ data64[8]) + ((XL64 << 8) ^ p512_23 ^ p512_08);
        m_state[9] = ((m_state[5] << 10) | (m_state[5] >> 54)) + ( XH64 ^ p512_25 ^ data64[9]) + ((XL64 >> 6) ^ p512_16 ^ p512_09);
        m_state[10] = ((m_state[6] << 11) | (m_state[6] >> 53)) + ( XH64 ^ p512_26 ^ data64[10]) + ((XL64 << 6) ^ p512_17 ^ p512_10);
        m_state[11] = ((m_state[7] << 12) | (m_state[7] >> 52)) + ( XH64 ^ p512_27 ^ data64[11]) + ((XL64 << 4) ^ p512_18 ^ p512_11);
        m_state[12] = ((m_state[0] << 13) | (m_state[0] >> 51)) + ( XH64 ^ p512_28 ^ data64[12]) + ((XL64 >> 3) ^ p512_19 ^ p512_12);
        m_state[13] = ((m_state[1] << 14) | (m_state[1] >> 50)) + ( XH64 ^ p512_29 ^ data64[13]) + ((XL64 >> 4) ^ p512_20 ^ p512_13);
        m_state[14] = ((m_state[2] << 15) | (m_state[2] >> 49)) + ( XH64 ^ p512_30 ^ data64[14]) + ((XL64 >> 7) ^ p512_21 ^ p512_14);
        m_state[15] = ((m_state[3] << 16) | (m_state[3] >> 48)) + ( XH64 ^ p512_31 ^ data64[15]) + ((XL64 >> 2) ^ p512_22 ^ p512_15);
    }

    void BMW512Base::FinalCompression()
    {
        ulong* tp512 = m_state;
        ulong p512_00 = (*tp512++) ^ 0xaaaaaaaaaaaaaaa0;
        ulong p512_01 = (*tp512++) ^ 0xaaaaaaaaaaaaaaa1;
        ulong p512_02 = (*tp512++) ^ 0xaaaaaaaaaaaaaaa2;
        ulong p512_03 = (*tp512++) ^ 0xaaaaaaaaaaaaaaa3;
        ulong p512_04 = (*tp512++) ^ 0xaaaaaaaaaaaaaaa4;
        ulong p512_05 = (*tp512++) ^ 0xaaaaaaaaaaaaaaa5;
        ulong p512_06 = (*tp512++) ^ 0xaaaaaaaaaaaaaaa6;
        ulong p512_07 = (*tp512++) ^ 0xaaaaaaaaaaaaaaa7;
        ulong p512_08 = (*tp512++) ^ 0xaaaaaaaaaaaaaaa8;
        ulong p512_09 = (*tp512++) ^ 0xaaaaaaaaaaaaaaa9;
        ulong p512_10 = (*tp512++) ^ 0xaaaaaaaaaaaaaaaa;
        ulong p512_11 = (*tp512++) ^ 0xaaaaaaaaaaaaaaab;
        ulong p512_12 = (*tp512++) ^ 0xaaaaaaaaaaaaaaac;
        ulong p512_13 = (*tp512++) ^ 0xaaaaaaaaaaaaaaad;
        ulong p512_14 = (*tp512++) ^ 0xaaaaaaaaaaaaaaae;
        ulong p512_15 = (*tp512++) ^ 0xaaaaaaaaaaaaaaaf;
        
        ulong td64_00 = (m_state[0] << 1) | (m_state[0] >> 63);
        ulong td64_01 = (m_state[1] << 2) | (m_state[1] >> 62);
        ulong td64_02 = (m_state[2] << 3) | (m_state[2] >> 61);
        ulong td64_03 = (m_state[3] << 4) | (m_state[3] >> 60);
        ulong td64_04 = (m_state[4] << 5) | (m_state[4] >> 59);
        ulong td64_05 = (m_state[5] << 6) | (m_state[5] >> 58);
        ulong td64_06 = (m_state[6] << 7) | (m_state[6] >> 57);
        ulong td64_07 = (m_state[7] << 8) | (m_state[7] >> 56);
        ulong td64_08 = (m_state[8] << 9) | (m_state[8] >> 55);
        ulong td64_09 = (m_state[9] << 10) | (m_state[9] >> 54);
        ulong td64_10 = (m_state[10] << 11) | (m_state[10] >> 53);
        ulong td64_11 = (m_state[11] << 12) | (m_state[11] >> 52);
        ulong td64_12 = (m_state[12] << 13) | (m_state[12] >> 51);
        ulong td64_13 = (m_state[13] << 14) | (m_state[13] >> 50);
        ulong td64_14 = (m_state[14] << 15) | (m_state[14] >> 49);
        ulong td64_15 = (m_state[15] << 16) | (m_state[15] >> 48);
        
        ulong t512_16 = p512_01 - p512_14;
        ulong t512_17 = p512_15 - p512_12;
        ulong t512_18 = p512_14 - p512_07;
        ulong t512_19 = p512_13 - p512_06;
        ulong t512_20 = p512_08 - p512_05;
        ulong t512_21 = p512_08 - p512_01;

        ulong p512_16 = (p512_05 + t512_18 + p512_10 + p512_13);
        p512_16 = ((p512_16 >> 1) ^ (p512_16 << 3) ^ ((p512_16 << 4) | (p512_16 >> 60)) ^ ((p512_16 << 37) | (p512_16 >> 27))) + 0xaaaaaaaaaaaaaaa1;
        ulong p512_17 = (p512_06 - p512_08 + p512_11 + p512_14 - p512_15);
        p512_17 = ((p512_17 >> 1) ^ (p512_17 << 2) ^ ((p512_17 << 13) | (p512_17 >> 51)) ^ ((p512_17 << 43) | (p512_17 >> 21))) + 0xaaaaaaaaaaaaaaa2;
        ulong p512_18 = (p512_00 + p512_07 + p512_09 + t512_17);
        p512_18 = ((p512_18 >> 2) ^ (p512_18 << 1) ^ ((p512_18 << 19) | (p512_18 >> 45)) ^ ((p512_18 << 53) | (p512_18 >> 11))) + 0xaaaaaaaaaaaaaaa3;
        ulong p512_19 = (p512_00 + t512_21 - p512_10 + p512_13);
        p512_19 = ((p512_19 >> 2) ^ (p512_19 << 2) ^ ((p512_19 << 28) | (p512_19 >> 36)) ^ ((p512_19 << 59) | (p512_19 >> 5))) + 0xaaaaaaaaaaaaaaa4;
        ulong p512_20 = (t512_16 + p512_02 + p512_09 - p512_11);
        p512_20 = ((p512_20 >> 1) ^ p512_20) + 0xaaaaaaaaaaaaaaa5;
        ulong p512_21 = (p512_03 - p512_02 + p512_10 + t512_17);
        p512_21 = ((p512_21 >> 1) ^ (p512_21 << 3) ^ ((p512_21 << 4) | (p512_21 >> 60)) ^ ((p512_21 << 37) | (p512_21 >> 27))) + 0xaaaaaaaaaaaaaaa6;
        ulong p512_22 = (p512_04 - p512_00 - p512_03 - p512_11 + p512_13);
        p512_22 = ((p512_22 >> 1) ^ (p512_22 << 2) ^ ((p512_22 << 13) | (p512_22 >> 51)) ^ ((p512_22 << 43) | (p512_22 >> 21))) + 0xaaaaaaaaaaaaaaa7;
        ulong p512_23 = (t512_16 - p512_04 - p512_05 - p512_12);
        p512_23 = ((p512_23 >> 2) ^ (p512_23 << 1) ^ ((p512_23 << 19) | (p512_23 >> 45)) ^ ((p512_23 << 53) | (p512_23 >> 11))) + 0xaaaaaaaaaaaaaaa8;
        ulong p512_24 = (p512_02 - p512_05 + t512_19 - p512_15);
        p512_24 = ((p512_24 >> 2) ^ (p512_24 << 2) ^ ((p512_24 << 28) | (p512_24 >> 36)) ^ ((p512_24 << 59) | (p512_24 >> 5))) + 0xaaaaaaaaaaaaaaa9;
        ulong p512_25 = (p512_00 - p512_03 + p512_06 + t512_18);
        p512_25 = ((p512_25 >> 1) ^ p512_25) + 0xaaaaaaaaaaaaaaaa;
        ulong p512_26 = (t512_21 - p512_04 - p512_07 + p512_15);
        p512_26 = ((p512_26 >> 1) ^ (p512_26 << 3) ^ ((p512_26 << 4) | (p512_26 >> 60)) ^ ((p512_26 << 37) | (p512_26 >> 27))) + 0xaaaaaaaaaaaaaaab;
        ulong p512_27 = (t512_20 - p512_00 - p512_02 + p512_09);
        p512_27 = ((p512_27 >> 1) ^ (p512_27 << 2) ^ ((p512_27 << 13) | (p512_27 >> 51)) ^ ((p512_27 << 43) | (p512_27 >> 21))) + 0xaaaaaaaaaaaaaaac;
        ulong p512_28 = (p512_01 + p512_03 - p512_06 - p512_09 + p512_10);
        p512_28 = ((p512_28 >> 2) ^ (p512_28 << 1) ^ ((p512_28 << 19) | (p512_28 >> 45)) ^ ((p512_28 << 53) | (p512_28 >> 11))) + 0xaaaaaaaaaaaaaaad;
        ulong p512_29 = (p512_02 + p512_04 + p512_07 + p512_10 + p512_11);
        p512_29 = ((p512_29 >> 2) ^ (p512_29 << 2) ^ ((p512_29 << 28) | (p512_29 >> 36)) ^ ((p512_29 << 59) | (p512_29 >> 5))) + 0xaaaaaaaaaaaaaaae;
        ulong p512_30 = (p512_03 + t512_20 - p512_11 - p512_12);
        p512_14 = ((p512_30 >> 1) ^ p512_30) + 0xaaaaaaaaaaaaaaaf;
        ulong p512_31 = (p512_12 - p512_04 + t512_19 - p512_09);
        p512_15 = ((p512_31 >> 1) ^ (p512_31 << 3) ^ ((p512_31 << 4) | (p512_31 >> 60)) ^ ((p512_31 << 37) | (p512_31 >> 27))) + 0xaaaaaaaaaaaaaaa0;

        p512_00 = p512_16;
        p512_01 = p512_17;
        p512_02 = p512_18;
        p512_03 = p512_19;
        p512_04 = p512_20;
        p512_05 = p512_21;
        p512_06 = p512_22;
        p512_07 = p512_23;
        p512_08 = p512_24;
        p512_09 = p512_25;
        p512_10 = p512_26;
        p512_11 = p512_27;
        p512_12 = p512_28;
        p512_13 = p512_29;

        p512_16 = ((p512_00 >> 1) ^ (p512_00 << 2) ^ ((p512_00 << 13) | (p512_00 >> 51)) ^ ((p512_00 << 43) | (p512_00 >> 21))) + 
                  ((p512_01 >> 2) ^ (p512_01 << 1) ^ ((p512_01 << 19) | (p512_01 >> 45)) ^ ((p512_01 << 53) | (p512_01 >> 11))) + 
                  ((p512_02 >> 2) ^ (p512_02 << 2) ^ ((p512_02 << 28) | (p512_02 >> 36)) ^ ((p512_02 << 59) | (p512_02 >> 5))) + 
                  ((p512_03 >> 1) ^ (p512_03 << 3) ^ ((p512_03 << 4) | (p512_03 >> 60)) ^ ((p512_03 << 37) | (p512_03 >> 27))) + 
                  ((p512_04 >> 1) ^ (p512_04 << 2) ^ ((p512_04 << 13) | (p512_04 >> 51)) ^ ((p512_04 << 43) | (p512_04 >> 21))) + 
                  ((p512_05 >> 2) ^ (p512_05 << 1) ^ ((p512_05 << 19) | (p512_05 >> 45)) ^ ((p512_05 << 53) | (p512_05 >> 11))) + 
                  ((p512_06 >> 2) ^ (p512_06 << 2) ^ ((p512_06 << 28) | (p512_06 >> 36)) ^ ((p512_06 << 59) | (p512_06 >> 5))) + 
                  ((p512_07 >> 1) ^ (p512_07 << 3) ^ ((p512_07 << 4) | (p512_07 >> 60)) ^ ((p512_07 << 37) | (p512_07 >> 27))) + 
                  ((p512_08 >> 1) ^ (p512_08 << 2) ^ ((p512_08 << 13) | (p512_08 >> 51)) ^ ((p512_08 << 43) | (p512_08 >> 21))) + 
                  ((p512_09 >> 2) ^ (p512_09 << 1) ^ ((p512_09 << 19) | (p512_09 >> 45)) ^ ((p512_09 << 53) | (p512_09 >> 11))) + 
                  ((p512_10 >> 2) ^ (p512_10 << 2) ^ ((p512_10 << 28) | (p512_10 >> 36)) ^ ((p512_10 << 59) | (p512_10 >> 5))) + 
                  ((p512_11 >> 1) ^ (p512_11 << 3) ^ ((p512_11 << 4) | (p512_11 >> 60)) ^ ((p512_11 << 37) | (p512_11 >> 27))) + 
                  ((p512_12 >> 1) ^ (p512_12 << 2) ^ ((p512_12 << 13) | (p512_12 >> 51)) ^ ((p512_12 << 43) | (p512_12 >> 21))) + 
                  ((p512_13 >> 2) ^ (p512_13 << 1) ^ ((p512_13 << 19) | (p512_13 >> 45)) ^ ((p512_13 << 53) | (p512_13 >> 11))) + 
                  ((p512_14 >> 2) ^ (p512_14 << 2) ^ ((p512_14 << 28) | (p512_14 >> 36)) ^ ((p512_14 << 59) | (p512_14 >> 5))) + 
                  ((p512_15 >> 1) ^ (p512_15 << 3) ^ ((p512_15 << 4) | (p512_15 >> 60)) ^ ((p512_15 << 37) | (p512_15 >> 27))) + 
                  ((td64_00 + td64_03 - td64_10 + 0x5555555555555550) ^ 0xaaaaaaaaaaaaaaa7);

        ulong XL64 = p512_16;

        p512_17 = ((p512_01 >> 1) ^ (p512_01 << 2) ^ ((p512_01 << 13) | (p512_01 >> 51)) ^ ((p512_01 << 43) | (p512_01 >> 21))) + 
                  ((p512_02 >> 2) ^ (p512_02 << 1) ^ ((p512_02 << 19) | (p512_02 >> 45)) ^ ((p512_02 << 53) | (p512_02 >> 11))) + 
                  ((p512_03 >> 2) ^ (p512_03 << 2) ^ ((p512_03 << 28) | (p512_03 >> 36)) ^ ((p512_03 << 59) | (p512_03 >> 5))) + 
                  ((p512_04 >> 1) ^ (p512_04 << 3) ^ ((p512_04 << 4) | (p512_04 >> 60)) ^ ((p512_04 << 37) | (p512_04 >> 27))) + 
                  ((p512_05 >> 1) ^ (p512_05 << 2) ^ ((p512_05 << 13) | (p512_05 >> 51)) ^ ((p512_05 << 43) | (p512_05 >> 21))) + 
                  ((p512_06 >> 2) ^ (p512_06 << 1) ^ ((p512_06 << 19) | (p512_06 >> 45)) ^ ((p512_06 << 53) | (p512_06 >> 11))) + 
                  ((p512_07 >> 2) ^ (p512_07 << 2) ^ ((p512_07 << 28) | (p512_07 >> 36)) ^ ((p512_07 << 59) | (p512_07 >> 5))) + 
                  ((p512_08 >> 1) ^ (p512_08 << 3) ^ ((p512_08 << 4) | (p512_08 >> 60)) ^ ((p512_08 << 37) | (p512_08 >> 27))) + 
                  ((p512_09 >> 1) ^ (p512_09 << 2) ^ ((p512_09 << 13) | (p512_09 >> 51)) ^ ((p512_09 << 43) | (p512_09 >> 21))) + 
                  ((p512_10 >> 2) ^ (p512_10 << 1) ^ ((p512_10 << 19) | (p512_10 >> 45)) ^ ((p512_10 << 53) | (p512_10 >> 11))) + 
                  ((p512_11 >> 2) ^ (p512_11 << 2) ^ ((p512_11 << 28) | (p512_11 >> 36)) ^ ((p512_11 << 59) | (p512_11 >> 5))) + 
                  ((p512_12 >> 1) ^ (p512_12 << 3) ^ ((p512_12 << 4) | (p512_12 >> 60)) ^ ((p512_12 << 37) | (p512_12 >> 27))) + 
                  ((p512_13 >> 1) ^ (p512_13 << 2) ^ ((p512_13 << 13) | (p512_13 >> 51)) ^ ((p512_13 << 43) | (p512_13 >> 21))) + 
                  ((p512_14 >> 2) ^ (p512_14 << 1) ^ ((p512_14 << 19) | (p512_14 >> 45)) ^ ((p512_14 << 53) | (p512_14 >> 11))) + 
                  ((p512_15 >> 2) ^ (p512_15 << 2) ^ ((p512_15 << 28) | (p512_15 >> 36)) ^ ((p512_15 << 59) | (p512_15 >> 5))) + 
                  ((p512_16 >> 1) ^ (p512_16 << 3) ^ ((p512_16 << 4) | (p512_16 >> 60)) ^ ((p512_16 << 37) | (p512_16 >> 27))) + 
                  ((td64_01 + td64_04 - td64_11 + 0x5aaaaaaaaaaaaaa5) ^ 0xaaaaaaaaaaaaaaa8);
        
        XL64 ^= p512_17;
        ulong TempEven64 = p512_14 + p512_12 + p512_10 + p512_08 + p512_06 + p512_04 + p512_02;
        ulong TempOdd64 = p512_15 + p512_13 + p512_11 + p512_09 + p512_07 + p512_05 + p512_03;

        p512_18 = TempEven64 + 
                  ((p512_03 << 5) | (p512_03 >> 59)) + 
                  ((p512_05 << 11) | (p512_05 >> 53)) + 
                  ((p512_07 << 27) | (p512_07 >> 37)) + 
                  ((p512_09 << 32) | (p512_09 >> 32)) + 
                  ((p512_11 << 37) | (p512_11 >> 27)) + 
                  ((p512_13 << 43) | (p512_13 >> 21)) + 
                  ((p512_15 << 53) | (p512_15 >> 11)) + 
                  ((p512_16 >> 1) ^ p512_16) + 
                  ((p512_17 >> 2) ^ p512_17) + 
                  ((td64_02 + td64_05 - td64_12 + 0x5ffffffffffffffa) ^ 0xaaaaaaaaaaaaaaa9);
        
        XL64 ^= p512_18;

        p512_19 = TempOdd64 + 
                  ((p512_04 << 5) | (p512_04 >> 59)) + 
                  ((p512_06 << 11) | (p512_06 >> 53)) + 
                  ((p512_08 << 27) | (p512_08 >> 37)) + 
                  ((p512_10 << 32) | (p512_10 >> 32)) + 
                  ((p512_12 << 37) | (p512_12 >> 27)) + 
                  ((p512_14 << 43) | (p512_14 >> 21)) + 
                  ((p512_16 << 53) | (p512_16 >> 11)) + 
                  ((p512_17 >> 1) ^ p512_17) + 
                  ((p512_18 >> 2) ^ p512_18) + 
                  ((td64_03 + td64_06 - td64_13 + 0x655555555555554f) ^ 0xaaaaaaaaaaaaaaaa);
        
        XL64 ^= p512_19;
        TempEven64 = TempEven64 + p512_16 - p512_02;

        p512_20 = TempEven64 + 
                  ((p512_05 << 5) | (p512_05 >> 59)) + 
                  ((p512_07 << 11) | (p512_07 >> 53)) + 
                  ((p512_09 << 27) | (p512_09 >> 37)) + 
                  ((p512_11 << 32) | (p512_11 >> 32)) + 
                  ((p512_13 << 37) | (p512_13 >> 27)) + 
                  ((p512_15 << 43) | (p512_15 >> 21)) + 
                  ((p512_17 << 53) | (p512_17 >> 11)) + 
                  ((p512_18 >> 1) ^ p512_18) + 
                  ((p512_19 >> 2) ^ p512_19) + 
                  ((td64_04 + td64_07 - td64_14 + 0x6aaaaaaaaaaaaaa4) ^ 0xaaaaaaaaaaaaaaab);

        XL64 ^= p512_20;
        TempOdd64 = TempOdd64 + p512_17 - p512_03;

        p512_21 = TempOdd64 + 
                  ((p512_06 << 5) | (p512_06 >> 59)) + 
                  ((p512_08 << 11) | (p512_08 >> 53)) + 
                  ((p512_10 << 27) | (p512_10 >> 37)) + 
                  ((p512_12 << 32) | (p512_12 >> 32)) + 
                  ((p512_14 << 37) | (p512_14 >> 27)) + 
                  ((p512_16 << 43) | (p512_16 >> 21)) + 
                  ((p512_18 << 53) | (p512_18 >> 11)) + 
                  ((p512_19 >> 1) ^ p512_19) + 
                  ((p512_20 >> 2) ^ p512_20) + 
                  ((td64_05 + td64_08 - td64_15 + 0x6ffffffffffffff9) ^ 0xaaaaaaaaaaaaaaac);

        XL64 ^= p512_21;
        TempEven64 += p512_18; TempEven64 -= p512_04;

        p512_22 = TempEven64 + 
                  ((p512_07 << 5) | (p512_07 >> 59)) + 
                  ((p512_09 << 11) | (p512_09 >> 53)) + 
                  ((p512_11 << 27) | (p512_11 >> 37)) + 
                  ((p512_13 << 32) | (p512_13 >> 32)) + 
                  ((p512_15 << 37) | (p512_15 >> 27)) + 
                  ((p512_17 << 43) | (p512_17 >> 21)) + 
                  ((p512_19 << 53) | (p512_19 >> 11)) + 
                  ((p512_20 >> 1) ^ p512_20) + 
                  ((p512_21 >> 2) ^ p512_21) + 
                  ((td64_06 + td64_09 - td64_00 + 0x755555555555554e) ^ 0xaaaaaaaaaaaaaaad);

        XL64 ^= p512_22;
        TempOdd64 += p512_19; TempOdd64 -= p512_05;

        p512_23 = TempOdd64 + 
                  ((p512_08 << 5) | (p512_08 >> 59)) + 
                  ((p512_10 << 11) | (p512_10 >> 53)) + 
                  ((p512_12 << 27) | (p512_12 >> 37)) + 
                  ((p512_14 << 32) | (p512_14 >> 32)) + 
                  ((p512_16 << 37) | (p512_16 >> 27)) + 
                  ((p512_18 << 43) | (p512_18 >> 21)) + 
                  ((p512_20 << 53) | (p512_20 >> 11)) + 
                  ((p512_21 >> 1) ^ p512_21) + 
                  ((p512_22 >> 2) ^ p512_22) + 
                  ((td64_07 + td64_10 - td64_01 + 0x7aaaaaaaaaaaaaa3) ^ 0xaaaaaaaaaaaaaaae);

        XL64 ^= p512_23;
        TempEven64 += p512_20; TempEven64 -= p512_06;

        p512_24 = TempEven64 + 
                  ((p512_09 << 5) | (p512_09 >> 59)) + 
                  ((p512_11 << 11) | (p512_11 >> 53)) + 
                  ((p512_13 << 27) | (p512_13 >> 37)) + 
                  ((p512_15 << 32) | (p512_15 >> 32)) + 
                  ((p512_17 << 37) | (p512_17 >> 27)) + 
                  ((p512_19 << 43) | (p512_19 >> 21)) + 
                  ((p512_21 << 53) | (p512_21 >> 11)) + 
                  ((p512_22 >> 1) ^ p512_22) + 
                  ((p512_23 >> 2) ^ p512_23) + 
                  ((td64_08 + td64_11 - td64_02 + 0x7ffffffffffffff8) ^ 0xaaaaaaaaaaaaaaaf);
        
        ulong XH64 = XL64 ^ p512_24;
        TempOdd64 += p512_21; TempOdd64 -= p512_07;

        p512_25 = TempOdd64 + 
                  ((p512_10 << 5) | (p512_10 >> 59)) + 
                  ((p512_12 << 11) | (p512_12 >> 53)) + 
                  ((p512_14 << 27) | (p512_14 >> 37)) + 
                  ((p512_16 << 32) | (p512_16 >> 32)) + 
                  ((p512_18 << 37) | (p512_18 >> 27)) + 
                  ((p512_20 << 43) | (p512_20 >> 21)) + 
                  ((p512_22 << 53) | (p512_22 >> 11)) + 
                  ((p512_23 >> 1) ^ p512_23) + 
                  ((p512_24 >> 2) ^ p512_24) + 
                  ((td64_09 + td64_12 - td64_03 + 0x855555555555554d) ^ 0xaaaaaaaaaaaaaaa0);
        
        XH64 ^= p512_25;
        TempEven64 += p512_22; TempEven64 -= p512_08;

        p512_26 = TempEven64 + 
                  ((p512_11 << 5) | (p512_11 >> 59)) + 
                  ((p512_13 << 11) | (p512_13 >> 53)) + 
                  ((p512_15 << 27) | (p512_15 >> 37)) + 
                  ((p512_17 << 32) | (p512_17 >> 32)) + 
                  ((p512_19 << 37) | (p512_19 >> 27)) + 
                  ((p512_21 << 43) | (p512_21 >> 21)) + 
                  ((p512_23 << 53) | (p512_23 >> 11)) + 
                  ((p512_24 >> 1) ^ p512_24) + 
                  ((p512_25 >> 2) ^ p512_25) + 
                  ((td64_10 + td64_13 - td64_04 + 0x8aaaaaaaaaaaaaa2) ^ 0xaaaaaaaaaaaaaaa1);

        XH64 ^= p512_26;
        TempOdd64 += p512_23; TempOdd64 -= p512_09;

        p512_27 = TempOdd64 + 
                  ((p512_12 << 5) | (p512_12 >> 59)) + 
                  ((p512_14 << 11) | (p512_14 >> 53)) + 
                  ((p512_16 << 27) | (p512_16 >> 37)) + 
                  ((p512_18 << 32) | (p512_18 >> 32)) + 
                  ((p512_20 << 37) | (p512_20 >> 27)) + 
                  ((p512_22 << 43) | (p512_22 >> 21)) + 
                  ((p512_24 << 53) | (p512_24 >> 11)) + 
                  ((p512_25 >> 1) ^ p512_25) + 
                  ((p512_26 >> 2) ^ p512_26) + 
                  ((td64_11 + td64_14 - td64_05 + 0x8ffffffffffffff7) ^ 0xaaaaaaaaaaaaaaa2);

        XH64 ^= p512_27;
        TempEven64 += p512_24; TempEven64 -= p512_10;

        p512_28 = TempEven64 + 
                  ((p512_13 << 5) | (p512_13 >> 59)) + 
                  ((p512_15 << 11) | (p512_15 >> 53)) + 
                  ((p512_17 << 27) | (p512_17 >> 37)) + 
                  ((p512_19 << 32) | (p512_19 >> 32)) + 
                  ((p512_21 << 37) | (p512_21 >> 27)) + 
                  ((p512_23 << 43) | (p512_23 >> 21)) + 
                  ((p512_25 << 53) | (p512_25 >> 11)) + 
                  ((p512_26 >> 1) ^ p512_26) + 
                  ((p512_27 >> 2) ^ p512_27) + 
                  ((td64_12 + td64_15 - td64_06 + 0x955555555555554c) ^ 0xaaaaaaaaaaaaaaa3);
        
        XH64 ^= p512_28;
        TempOdd64 += p512_25; TempOdd64 -= p512_11;

        p512_29 = TempOdd64 + 
                  ((p512_14 << 5) | (p512_14 >> 59)) + 
                  ((p512_16 << 11) | (p512_16 >> 53)) + 
                  ((p512_18 << 27) | (p512_18 >> 37)) + 
                  ((p512_20 << 32) | (p512_20 >> 32)) + 
                  ((p512_22 << 37) | (p512_22 >> 27)) + 
                  ((p512_24 << 43) | (p512_24 >> 21)) + 
                  ((p512_26 << 53) | (p512_26 >> 11)) + 
                  ((p512_27 >> 1) ^ p512_27) + 
                  ((p512_28 >> 2) ^ p512_28) + 
                  ((td64_13 + td64_00 - td64_07 + 0x9aaaaaaaaaaaaaa1) ^ 0xaaaaaaaaaaaaaaa4);

        XH64 ^= p512_29;
        TempEven64 += p512_26; TempEven64 -= p512_12;

        p512_30 = TempEven64 + 
                  ((p512_15 << 5) | (p512_15 >> 59)) + 
                  ((p512_17 << 11) | (p512_17 >> 53)) + 
                  ((p512_19 << 27) | (p512_19 >> 37)) + 
                  ((p512_21 << 32) | (p512_21 >> 32)) + 
                  ((p512_23 << 37) | (p512_23 >> 27)) + 
                  ((p512_25 << 43) | (p512_25 >> 21)) + 
                  ((p512_27 << 53) | (p512_27 >> 11)) + 
                  ((p512_28 >> 1) ^ p512_28) + 
                  ((p512_29 >> 2) ^ p512_29) + 
                  ((td64_14 + td64_01 - td64_08 + 0x9ffffffffffffff6) ^ 0xaaaaaaaaaaaaaaa5);
        
        XH64 ^= p512_30;
        TempOdd64 += p512_27; TempOdd64 -= p512_13;

        p512_31 = TempOdd64 + 
                  ((p512_16 << 5) | (p512_16 >> 59)) + 
                  ((p512_18 << 11) | (p512_18 >> 53)) + 
                  ((p512_20 << 27) | (p512_20 >> 37)) + 
                  ((p512_22 << 32) | (p512_22 >> 32)) + 
                  ((p512_24 << 37) | (p512_24 >> 27)) + 
                  ((p512_26 << 43) | (p512_26 >> 21)) + 
                  ((p512_28 << 53) | (p512_28 >> 11)) + 
                  ((p512_29 >> 1) ^ p512_29) + 
                  ((p512_30 >> 2) ^ p512_30) + 
                  ((td64_15 + td64_02 - td64_09 + 0xa55555555555554b) ^ 0xaaaaaaaaaaaaaaa6);
        
        XH64 ^= p512_31;

        m_state[0] = ((XH64 << 5) ^ (p512_16 >> 5) ^ m_state[0]) + ( XL64 ^ p512_24 ^ p512_00);
        m_state[1] = ((XH64 >> 7) ^ (p512_17 << 8) ^ m_state[1]) + ( XL64 ^ p512_25 ^ p512_01);
        m_state[2] = ((XH64 >> 5) ^ (p512_18 << 5) ^ m_state[2]) + ( XL64 ^ p512_26 ^ p512_02);
        m_state[3] = ((XH64 >> 1) ^ (p512_19 << 5) ^ m_state[3]) + ( XL64 ^ p512_27 ^ p512_03);
        m_state[4] = ((XH64 >> 3) ^ p512_20 ^ m_state[4]) + ( XL64 ^ p512_28 ^ p512_04);
        m_state[5] = ((XH64 << 6) ^ (p512_21 >> 6) ^ m_state[5]) + ( XL64 ^ p512_29 ^ p512_05);
        m_state[6] = ((XH64 >> 4) ^ (p512_22 << 6) ^ m_state[6]) + ( XL64 ^ p512_30 ^ p512_06);
        m_state[7] = ((XH64 >> 11) ^ (p512_23 << 2) ^ m_state[7]) + ( XL64 ^ p512_31 ^ p512_07);

        m_state[8] = ((m_state[4] << 9) | (m_state[4] >> 55)) + ( XH64 ^ p512_24 ^ m_state[8]) + ((XL64 << 8) ^ p512_23 ^ p512_08);
        m_state[9] = ((m_state[5] << 10) | (m_state[5] >> 54)) + ( XH64 ^ p512_25 ^ m_state[9]) + ((XL64 >> 6) ^ p512_16 ^ p512_09);
        m_state[10] = ((m_state[6] << 11) | (m_state[6] >> 53)) + ( XH64 ^ p512_26 ^ m_state[10]) + ((XL64 << 6) ^ p512_17 ^ p512_10);
        m_state[11] = ((m_state[7] << 12) | (m_state[7] >> 52)) + ( XH64 ^ p512_27 ^ m_state[11]) + ((XL64 << 4) ^ p512_18 ^ p512_11);
        m_state[12] = ((m_state[0] << 13) | (m_state[0] >> 51)) + ( XH64 ^ p512_28 ^ m_state[12]) + ((XL64 >> 3) ^ p512_19 ^ p512_12);
        m_state[13] = ((m_state[1] << 14) | (m_state[1] >> 50)) + ( XH64 ^ p512_29 ^ m_state[13]) + ((XL64 >> 4) ^ p512_20 ^ p512_13);
        m_state[14] = ((m_state[2] << 15) | (m_state[2] >> 49)) + ( XH64 ^ p512_30 ^ m_state[14]) + ((XL64 >> 7) ^ p512_21 ^ p512_14);
        m_state[15] = ((m_state[3] << 16) | (m_state[3] >> 48)) + ( XH64 ^ p512_31 ^ m_state[15]) + ((XL64 >> 2) ^ p512_22 ^ p512_15);
    }

    void BMWBase::Initialize()
    {
        m_processedBytes = 0;
        m_buffer_pos = 0;
    }

    void BMW256Base::Initialize()
    {
        if (HashSize == 28)
            memcpy(m_state, initial_state_224, 16 * sizeof(uint));
        else
            memcpy(m_state, initial_state_256, 16 * sizeof(uint));

        BMWBase::Initialize();
    }

    void BMW512Base::Initialize()
    {
        if (HashSize == 48)
            memcpy(m_state, initial_state_384, 16 * sizeof(ulong));
        else
            memcpy(m_state, initial_state_512, 16 * sizeof(ulong));

        BMWBase::Initialize();
    }

    void BMWBase::TransformBytes(byte* a_data, int a_index, int a_length)
    {
        int last = a_length + a_index - 1;

        int j = a_index;
        while (m_buffer_pos < BlockSize && j <= last)
        {
            m_buffer[m_buffer_pos++] = a_data[j++];
            m_processedBytes++;
        }

        if (m_buffer_pos < BlockSize)
            return; 

        TransformBlock(m_buffer, 0);
        m_buffer_pos = 0;
        memset(m_buffer, 0, BlockSize);

        while ((j + BlockSize - 1) <= last)
        {
            TransformBlock(a_data, j);
            m_processedBytes += BlockSize;

            j += BlockSize;
        }

        m_buffer_pos = m_processedBytes % 64;
        while (j <= last)
        {
            m_buffer[m_buffer_pos++] = a_data[j++];
            m_processedBytes++;
        }
    }

    void BMW256Base::Finish()
    {
        int databitlen;

        m_buffer[m_buffer_pos] = m_buffer[m_buffer_pos] & 0xff00 ^ 0x80;
        ulong* data64 = (ulong*)m_buffer;

        if (m_processedBytes % BlockSize < 56)
        {
            memset(m_buffer + m_buffer_pos + 1, 0, 55 - m_buffer_pos);
            databitlen = 512;
            data64[7] = m_processedBytes * 8;
        }
        else
        {
            memset(m_buffer + m_buffer_pos + 1, 0, 119 - m_buffer_pos);
            databitlen = 1024;
            data64[15] = m_processedBytes * 8;
        }

        uint* data32 = (uint*)m_buffer;
        uint* p256 = m_state;

        while (databitlen >= 512)
        {
            databitlen -= 512;
            TransformBlock((byte*)data32, 0);
            data32 += 16;
        }
        
        FinalCompression();      
    }

    void BMW512Base::Finish()
    {
        int databitlen;

        m_buffer_pos = m_processedBytes % BlockSize;

        m_buffer[m_buffer_pos] = m_buffer[m_buffer_pos] & 0xff00 ^ 0x80;

        ulong* data64 = (ulong*)m_buffer;

        if (m_processedBytes % BlockSize < 120)
        {
            memset(m_buffer + m_buffer_pos + 1, 0, 119 - m_buffer_pos);
            databitlen = 1024;
            data64[15] = m_processedBytes * 8;
        }
        else
        {
            memset(m_buffer + m_buffer_pos + 1, 0, 247 - m_buffer_pos);
            databitlen = 2048;
            data64[31] = m_processedBytes * 8;
        }

        ulong* p512 = m_state;

        while (databitlen >= 512)
        {
            databitlen -= 1024;
            TransformBlock((byte*)data64, 0);
            data64 += 16;
        }
        
        FinalCompression();
    }

    byte* BMW256Base::GetResult()
    {
        byte* hashval = new byte[HashSize];

        if (HashSize == 28)
            memcpy(hashval, m_state + 9, 28);
        else
            memcpy(hashval, m_state + 8, 32);

        return hashval;
    }

    byte* BMW512Base::GetResult()
    {
        byte* hashval = new byte[HashSize];

        if (HashSize == 48)
            memcpy(hashval, m_state + 10, 48);
        else
            memcpy(hashval, m_state + 8, 64);

        return hashval;
    }

    byte* BMWBase::ComputeBytes(byte* a_data, int a_length)
    {
        Initialize();
        TransformBytes(a_data, 0, a_length);
        return TransformFinal();
    }
}